vue中与Svelte响应式写法
计数器
vue
var vm = new Vue({
data: {
count: 0
},
computed: {
double: function () {
return this.count * 2
}
}
})
Svelte
let count = 0;
function handleClick() {
count += 1;
}
$: double = count * 2
</script>
<button on:click={handleClick}>
Clicked {double} times
</button>
上面例子中每次点击视图都会更新并增加2
Svelte 响应式原理
- 实现一个todolist
- 原生怎么去实现
然后每次新增/删除/修改任务时,除了修改 tasks 数据,都需要手动触发重新渲染 tasks
(当然这样的实现并不好,每次删除/插入太多 DOM 节点性能会有问题
- react
页面操作后 有 三步曲
- 首先是调度器,这里主要是为了处理优先级(用户点击事件属于高优先级)和合成事件
- 第二个部分是 Render 阶段,这里主要是遍历节点,找到需要更新的 Fiber Node,执行 Diff 算法计算需要执行那种类型的操作,打上 effectTag,生成一条带有 effectTag 的 Fiber Node 链表。常说的异步可中断也是发生在这个阶段。
- 第三个阶段是 Commit,这一步要做的事情是遍历第二步生成的链表,依次执行对应的操作(是新增,还是删除,还是修改…)
- vue
大致过程是编译过程中收集依赖,基于 Proxy(3.x) ,defineProperty(2.x) 的 getter,setter 实现在数据变更时通知 Watcher。Vue
的实现很酷,每次修改 data
上的数据都像在施魔法。
- Svelte
Svelte 源代码主要分成 compiler 和 runtime 两部分
例子
<script>
let name = "world";
function setName() {
name = "fesky";
}
</script>
<h1 on:click={setName}>Hello {name}!</h1>
经过编译之后
前面例子tolist 中 我们在每次修改数据之后,都要手动重新渲染 DOM!我们不提倡这么写法,因为难以维护
而 Svelte Compile 实际上就是在代码编译阶段帮我们实现了这件事!把需要数据变更之后做的事情都分析出来生成原生 JS 代码,运行时就不需要像 Vue Proxy
那样的运行时代码了
Fragment—— DOM 操作
create_fragment里面都有什么
主要看以下四个钩子方法:
c(create) :在这个钩子里面创建 DOM 节点,创建完之后保存在每个 fragment 的闭包内。
m(mount) :挂载 DOM 节点到 target 上,在这里进行事件的板顶。
p(update) :组件数据发生变更时触发,在这个方法里面检查更新。
d(destroy) :移除挂载,取消事件绑定。
编译结果会从 svelte/internal
中引入 text
,element
,append
,detach
,listen
等等的方法。源码中可以看到,都是一些非常纯粹的 DOM 操作。
-
$$invalidate
整体思路
- 修改数据,调用
$$invalidate
方法 - 判断是否相等,标记脏数据,
make_dirty
- 在 microTask 中触发更新,遍历所有
dirty_component
, 更新 DOM 节点 - 重置 Dirty
原文链接:https://juejin.cn/post/7234058546572574780 作者:z_c