Aus*_*ela 4 javascript svelte svelte-3 sveltekit
我有两个变量a
,b
加起来为 100。如何设置反应式声明,以便 whena
更改b
为 be ,100 - a
反之亦然?当我尝试类似的事情时
let total = 100;
$: a = total - b;
$: b = total - a;
Run Code Online (Sandbox Code Playgroud)
我收到“检测到循环依赖性”错误。有什么办法可以完成这件事吗?
rix*_*ixo 12
问题来自于这样一个事实:Svelte 希望按照反应块相互依赖的顺序对它们进行排序:它希望首先计算那些依赖但没有依赖关系的块,以避免不必要的计算......或者陷入困境环形。
此外,Svelte 考虑了反应式表达式中出现的任何反应式变量的依赖性。
因此,错误的实际来源是变量a
和 都b
出现在两个反应式表达式中。
解决方案是从反应式表达式中删除不需要的变量,即分配给的变量。这可以通过将分配移至反应块外部的函数来完成。不幸的是,它更冗长......
<script>
let total = 100;
let a = 0
let b = 0
const setA = () => {
// the assignment to a (or b in the other function) are still
// reactive, of course, but Svelte won't propagate changes to
// variable that are assigned their current value, so this
// will break the loop
a = total - b
}
const setB = () => {
b = total - a
}
$: setA(total - b);
$: setB(total - a);
</script>
<pre>
a: {a}
b: {b}
</pre>
<label>
a <input type="number" bind:value={a} />
</label>
<label>
b <input type="number" bind:value={b} />
</label>
Run Code Online (Sandbox Code Playgroud)
编辑
正如 @avf 在评论中所说,上面的代码具有误导性,对于代码的读者来说并不那么明显。我当时这样写是因为我专注于演示 Svelte 反应性的原理。
在现实世界中,我宁愿推荐以下两种形式中的任何一种。
只要有可能,就倾向于显而易见:
// this function is just normal
const setA = (value) => {
a = value
}
// this reactive expression makes it obvious and straightforward that
// its dependencies are total and b, and only those
$: setA(total - b)
Run Code Online (Sandbox Code Playgroud)
当明显性不是一个选项时(例如,因为函数的内容比单纯的赋值更具副作用),我会依赖以下对于 Svelte 来说非常惯用的形式。不幸的是,对于那些通常不熟悉 Svelte 的人来说,它也非常晦涩……但我想这只是属于你必须学习才能真正精通该框架的事情。
const recomputeEverythingOrWhatever = () => {
...
}
// in Svelte lingo, this is broadly understood as "whenever a, or b, or
// total changes, then recompute everything (or whatever)"
$: a, b, total, recomputeEverythingOrWhatever()
Run Code Online (Sandbox Code Playgroud)
在我看来,这种语法很好,因为 Svelte 开发人员普遍熟悉并理解它。
但要小心在重新计算函数中输入的内容。如果它改变了响应式块的依赖项的值,这次代码将编译得很好,Svelte 甚至会在运行时中断更新循环以避免冻结 JS 线程......但是您最终可能会得到这样的代码:很难理解或预测。
归档时间: |
|
查看次数: |
1174 次 |
最近记录: |