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

Posted

技术标签:

【中文标题】Svelte 内部结构:反应式声明语法如何工作【英文标题】:Svelte internals: how does reactive declaration syntax work 【发布时间】:2019-12-05 08:22:24 【问题描述】:

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

如果这看起来有点陌生,请不要担心。它是有效的(如果非常规)javascript,Svelte 将其解释为“只要任何引用的值发生变化,就重新运行此代码”

常规的javascript功能引用似乎是labels(请确认)

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

有一个githb issue 最终开放解释纤细的内部结构。

【问题讨论】:

尝试在svelte.dev/repl 中创建一个简单的示例并检查右侧的 JS 输出。 【参考方案1】:

确实是标签语法。

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

在哪里可以找到代码:

编译代码后,您可以在组件生命周期的状态更新部分中找到响应式声明。然而,这段代码不会在与 DOM 更新 相关的 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); 

希望它有助于解决问题。

【讨论】:

以上是关于Svelte 内部结构:反应式声明语法如何工作的主要内容,如果未能解决你的问题,请参考以下文章

PHP 内部结构:TSRMLS_FETCH 是如何工作的?

了解如何从内部函数更新原始二维数组

如何在 MySQL 中声明内部表?

如何在 Svelte 的类属性中使用反应函数?

如何阅读反应语法

JavaScript是如何工作的:深入类和继承内部原理 + Babel和TypeScript之间转换