Svelte 内部结构:反应式声明语法如何工作

Svelte internals: how does reactive declaration syntax work

关于 svelte 中的响应式声明 $: doubled = count*2,它在 svelte tutorial 中声明

Don't worry if this looks a little alien. It's valid (if unconventional) JavaScript, which Svelte interprets to mean 're-run this code whenever any of the referenced values change'

常规的javascript特征引用似乎是labels(请确认)

请用简单的语言解释 svelte 编译器是如何做到这一点的,并提供对编译器代码中发生这种情况[或开始发生]的位置的引用

有一个 githb issue 最终会解释 svelte 的内部结构。

确实是标签语法

Javascript 标签几乎没有用处,因此这是一种创建简单语法并确保它能很好地与 linter 和 IDE 配合使用的优雅方法。

在哪里可以找到代码:

编译代码后,您可以在组件生命周期的 state update 部分找到响应式声明。但是这段代码不会在与DOM update相关的beforeUpdate和afterUpdate之间执行。如果您更改这些回调中的值,您可能会得到一些古怪的结果,因为反应语句可能不会更新。

在代码中查找$$self.$$.update即可。

工作原理:

编译器正在分析这些语句以查找要观察哪些变量的变化。这些变量是赋值运算符的所有权利,或者是函数调用中的每个参数。值得注意的是,const 变量不会被观察到,因为它们永远不会改变。

$: doubled = count * 2;

将编译为

if ($$dirty.count) { $$invalidate('doubled', doubled = count * 2); }

$$dirty 是更新生命周期接收的参数,它是一个包含每个可能修改的变量的属性的对象,当对其调用 $$invalidate 时,这些属性设置为 1。

Svelte 然后在生命周期更新部分的末尾添加这些语句,并根据上述观察到的至少一个变量的变化来执行它们。

Svelte 还按拓扑顺序对这些语句进行排序。这意味着使用另一个反应语句结果的反应语句将在之后被评估。无论您以何种顺序将它们放入代码中。

$: quadrupled = doubled * 2;
$: doubled = count * 2;

仍将正确编译为

if ($$dirty.count) { $$invalidate('doubled', doubled = count * 2); }
if ($$dirty.doubled) { $$invalidate('quadrupled', quadrupled = doubled * 2); }

希望它有助于解决问题。