我有几十个反应式原始值(例如
div_status = "frozen"
),我需要在组件/模块边界之间传递,包括+page.svelte
文件和svelte.js
模块。这些值表示 UI 的可更改属性,因此将影响 (a) 样式以及 (b) 某些事件侦听器内用于用户交互的 if-else 块。重要的是,这些值需要在拖动级别上“反应式”,因为 UI 必须在用户拖动时做出响应(例如,将鼠标悬停在拖放区域上、拖动特定距离等)
将我的代码库转换为 Svelte 5,我不确定对于此用例是否使用商店或$state()
。
svelte.js
模块的导出函数中使用它们。此外,它们
很难重构。
$state()
(如
$state("frozen")
)的问题是,我必须使事情复杂化,以免重新分配/覆盖状态:因此,为了改变它们的值,我要么将多个基元组合到对象数组中或将它们单独炸毁(例如
div_status = {value: "frozen"}
)。
$state()
的选择是否取决于我选择使用 context-API 还是只是将它们作为 props 传递。总而言之,我正在寻找一个易于重构的解决方案。
更新svelte.js
文件内的商店,如下所示:
stores.js
export let simpleStore = writable(1);
export let comboStore = writable({a:1});
import { simpleStore, comboStore } from '$lib/stores.js'
export function handleIncrease() {
simpleStore.update(value => value + 1);
comboStore.update(value => {
return { ...value, a: value.a + 1 };
});
}
<script>
import { simpleStore, comboStore } from '$lib/stores.js'
</script>
<p>{$simpleStore}</p>
<p>{$comboStore.a}</p>
<button onclick={handleIncrease}>Increase a</button>
$state
本身并不是问题。按值传递的原语会阻止更新;这也可以在普通 JS 中观察到,例如
function createCounter() {
let value = 0;
setTimeout(() => value++); // happens later
return value;
}
const counter = createCounter();
console.log('Value copied', counter)
setTimeout(() => console.log('Value copied', counter), 1);
您需要通过函数或访问器属性维护对该值的
引用。
function createCounter() {
let value = 0;
setTimeout(() => value++); // happens later
return () => value;
}
const counter = createCounter();
console.log('Value referenced', counter())
setTimeout(() => console.log('Value referenced', counter()), 1);
一般来说,在 Svelte 5 中应该在商店上使用符文;商店可能会在以后的版本中被弃用,因为符文应该能够取代它们。
如果您处于只读状态,您可以返回一个如上例所示的函数,并通过
$derived.by
“接收”该函数。例如
function createCounter() {
let value = $state(0);
setTimeout(() => value++); // happens later
return () => value;
}
const counter = $derived.by(createCounter());
$inspect('Counter', counter);
预览 REPL1 对于写访问,还有各种选项,例如使用两个函数(获取/设置)或使用
{ value }
框。盒子方法可能是最灵活的,因为它允许将对象用于诸如
bind:value={...}
之类的事情。您还可以轻松地将这样的对象传递到上下文中;上下文主要用于将某些内容传递到组件层次结构的多个级别。如前所述,通过 props,您可以直接使用值的绑定来发送和接收值的更新。
拥有许多正在传递的原语可能暗示着优化机会。也许其中一些可以分组并放在一个更大的
$state
对象上,其属性名称比“值”更有意义。
使用什么通常取决于当前的具体问题。有时,仅提供对状态和定制更新功能的读取访问可能是最好的方法。
1 链接稍后可能会中断并需要更新。