我想知道 Svelte 的内部结构,以便正确设计我的应用程序以实现最高效率(我可能会处理(数万?)成千上万个要更新的元素,因此效率很重要),尤其是如何实现反应性。因此,使用这个小示例(在链接上,您可以在右侧选项卡上检查 JS 代码),我实现了这个基本代码:
<script>
let foo = $state(42);
let bar = $state(52);
</script>
<div onclick={() => foo = foo + 2}>
Hello {foo}
</div>
<span onclick={() => bar = bar + 1}>
Hello {bar}
</span>
我得到了以下编译后的 JavaScript:
import 'svelte/internal/disclose-version';
import * as $ from 'svelte/internal/client';
var on_click = (_, foo) => $.set(foo, $.get(foo) + 2);
var on_click_1 = (__1, bar) => $.set(bar, $.get(bar) + 1);
var root = $.template(`<div> </div> <span> </span>`, 1);
export default function App($$anchor) {
let foo = $.state(42);
let bar = $.state(52);
var fragment = root();
var div = $.first_child(fragment);
div.__click = [on_click, foo];
var text = $.child(div);
$.reset(div);
var span = $.sibling(div, 2);
span.__click = [on_click_1, bar];
var text_1 = $.child(span);
$.reset(span);
$.template_effect(() => {
$.set_text(text, `Hello ${$.get(foo) ?? ''}`);
$.set_text(text_1, `Hello ${$.get(bar) ?? ''}`);
});
$.append($$anchor, fragment);
}
$.delegate(['click']);
看起来重要的是代码:
$.template_effect(() => {
$.set_text(text, `Hello ${$.get(foo) ?? ''}`);
$.set_text(text_1, `Hello ${$.get(bar) ?? ''}`);
});
如果我对信号的理解是正确的(我遵循了这篇很棒的文章来了解信号是如何实现的),那么每次内部信号发生变化时,都会运行回调函数……但问题是,如果bar
发生变化,代码$.set_text(text, `Hello ${$.get(foo) ?? ''}`);
也会发生变化,即改变一个信号会触发 O(n)操作,其中 n 是信号的数量……对于 2 个元素来说这并不多,但如果我有数万个元素,恐怕更新时间就不可忽略了。
我有两个问题:
- 为什么 Svelte 不为每个信号实现一个回调,以实现与信号数量无关的 O(1)复杂度?
- 另外,可观察对象是否遵循相同的想法?我的最终目标是了解 Dexie.js
liveQuery
可观察对象中更新的复杂性。