
在我最近发布 svelte 5 迁移的经验和注意事项之后,我想重点介绍从 svelte 4 迁移到 svelte 5 时的一些技巧和心态的变化。
svelte 4 使用“神奇的”$: 并让和完成所有繁重的工作以使代码具有反应性。我们还接受了变量重新分配,例如
<script> let arr = [1, 2, 3] let value = 4 arr = [...arr, value] </script>
而不是更新/改变变量的方法,如推送等
我很惊讶能够使用 svelte 5 重新学习好的旧 js 模式。
而且我可能也被 svelte 4 中的 let 宠坏了,没有考虑反应性,如果需要的话它会被包含在内。 但并非所有变量都必须是反应性的。非反应性变量也可以在反应性甚至“传统变异代码”中更新。反应式变量的真正需要是当我们在 ui 中使用它时(当这个变量在 html/页面中呈现并且我们需要它稍后更新时)。
您可能会在 svelte 5 中遇到错误,例如无法分配给派生状态,在其自己的范围内引用的状态永远不会更新。您的意思是在闭包内引用它吗?或衍生_引用_selfn如果使用 svelte 4 编码风格,则派生值无法递归引用自身。
看一下这个 svelte 4 风格的代码示例:
<script>
let value;
let derivedarr = []
$: if (value) {
derivedarr = [...derivedarr, value]
}
function random () {
value = math.floor(1 + math.random() * 10)
}
</script>
<button on:click={random}>generate random value</button>
<p>value: {value}</p>
<p>derivedarr: {derivedarr}</p>
演示
我们有两个反应变量,svelte 4 自动解决更新问题。我们只需要记住正确的方法是重新分配变量。
在 svelte 5 中,我们应该思考如何实现相同的结果。我们使用的两个变量还不够,我们还需要一个,即辅助变量。
首选方法是使用 $driven() 符文。
在思高数码商城的基础上经过大量修改完善而成,引入了新的功能 此商城比较简洁,但功能完整。 1.支持产品多图:略图,小图,大图,多图。 2.市场价与热卖价对比。 3.注册与否均可购物。有很多人讨厌注册,这个功能正好迎合了这部分人的使用习惯。 4.除了常见商城的左侧分类树外,还有顶端分类菜单。 5.有友情链接模块。 6.大多功能均制作成独立模块 更新内容: 1.页顶分类菜单——老版本中需要手工修改页面
4
<script>
let value = $state();
let helperarr = [];
let derivedarr = $derived.by(() => {
if (value) {
helperarr.push(value);
return helperarr;
}
});
function random () {
value = math.floor(1 + math.random() * 10)
}
</script>
<button onclick={random}>generate random value</button>
<p>value: {value}</p>
<p>derivedarr: {derivedarr}</p>
演示
如果您知道更简单的方法,请告诉我。
还有一个 $effect() 符文方法可以实现相同的效果。它可能看起来更简单,但我们应该尽可能避免效果(主要是 svetlet 5 效果不在服务器/ssr 上运行)。
<script>
let value = $state();
let helperarr = []
let effectarr = $derived(helperarr);
$effect.pre(() => {
if (value) {
helperarr.push(value)
}
})
function random () {
value = math.floor(1 + math.random() * 10)
}
</script>
<button onclick={random}>generate random value</button>
<p>value: {value}</p>
<p>effectarr: {effectarr}</p>
演示
这是我尝试将 svelte 4 页面直接迁移到 svelte 5 的示例。我花了一段时间重新思考代码。此页面用作帖子搜索,具有“加载更多”功能(如果用户没有 js,则添加结果或分页):
苗条4
<script>
import icon from '../components/icon.svelte';
import { enhance } from '$app/forms';
import { tick } from 'svelte';
export let form;
export let searchinglang;
export let l;
let results = [];
let previoussearch = '';
let searchterm;
let skip;
$: if (!!form && form?.thereismore) {
searchterm = form.searchterm;
skip = number(form?.skip) + 20;
}
$: if (!!form?.searchresultfromaction) {
if (previoussearch == form.searchterm && form.therewasmore) {
results = [...results, ...form.searchresultfromaction];
} else {
results = [...form.searchresultfromaction];
previoussearch = form.searchterm;
}
}
async function intoview(el) {
await tick();
if (el.attributes.index.nodevalue == skip - 20 && skip != undefined) {
el.scrollintoview({ behavior: 'smooth' });
}
}
</script>
{#if results.length}
<ol>
{#each results as item, index}
<li use:intoview {index} aria-posinset={index}>
<!-- users without javascript have calculated order of results within paggination and css disables standard ol ul numbering -->
<!-- users with javascript have standard ol ul numbering and loading more feature -->
<noscript>{number(index) + 1 + number(form?.skip)}. </noscript>
<a href="/act/{searchinglang}/{item.id}/present/text">{item.title}</a>
</li>
{/each}
</ol>
{#if form?.thereismore}
<form
method="post"
action="?/search&skip={skip}&therewasmore={form?.thereismore}"
use:enhance
autocomplete="off"
>
<label>
<!-- probably we do not need to bind the value as this is hidden input -->
<!-- <input name="searchterm" type="hidden" bind:value={searchterm} /> -->
<input name="searchterm" type="hidden" value={searchterm} />
</label>
<button aria-label="button to load more search results" class="outline">
<icon name="loadmore" />
</button>
</form>
{/if}
{:else if form?.searchresultfromaction.length == 0}
{l.noresultsfound}
{/if}
<style>
@media (scripting: none) {
/* users without javascript have calculated order of results within paggination and css disables standard ol ul numbering
users with javascript have standard ol ul numbering and loading more feature */
ol {
list-style-type: none;
}
}
</style>
苗条5
<script>
import Icon from '../components/Icon.svelte';
import { enhance } from '$app/forms';
import { tick } from 'svelte';
let { form, searchingLang, l } = $props();
let previousSearch = '';
let skip = $derived.by(() => {
if (!!form && form?.thereIsMore) {
return Number(form?.skip) + 20;
}
});
let helperResultsArr = [];
let results = $derived.by(() => {
if (!!form?.searchResultFromAction) {
if (previousSearch == form.searchTerm && form.thereWasMore) {
helperResultsArr.push(...form.searchResultFromAction);
return helperResultsArr;
} else {
helperResultsArr = [];
helperResultsArr.push(...form.searchResultFromAction);
previousSearch = form.searchTerm;
return helperResultsArr;
}
} else return [];
});
async function intoView(el) {
await tick();
if (el.attributes.index.nodeValue == skip - 20 && skip != undefined) {
el.scrollIntoView({ behavior: 'smooth' });
}
}
</script>
{#if results.length}
<ol>
{#each results as item, index}
<li use:intoView {index} aria-posinset={index}>
<!-- users without javascript have calculated order of results within paggination and css disables standard ol ul numbering -->
<!-- users with javascript have standard ol ul numbering and loading more feature -->
<noscript>{Number(index) + 1 + Number(form?.skip)}. </noscript>
<a href="/act/{searchingLang}/{item.id}/present/text">{item.title}</a>
</li>
{/each}
</ol>
{#if form?.thereIsMore}
<form
method="POST"
action="?/search&skip={skip}&thereWasMore={form?.thereIsMore}"
use:enhance
autocomplete="off"
>
<label>
<input name="searchTerm" type="hidden" value={form.searchTerm} />
</label>
<button aria-label="Button to load more search results" class="outline">
<Icon name="loadMore" />
</button>
</form>
{/if}
{:else if form?.searchResultFromAction.length == 0}
{l.noResultsFound}
{/if}
<style>
@media (scripting: none) {
/* users without javascript have calculated order of results within paggination and css disables standard ol ul numbering
users with javascript have standard ol ul numbering and loading more feature */
ol {
list-style-type: none;
}
}
</style>
现在就这些了。
ps:如果您愿意以不同的方式进行迁移,请随时告诉我。
以上就是Svelte 5 中的“助手”变量的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号