Svelte - Svelte 与传统框架有什么不同?为什么感觉 Svelte 其实才是 Vue3?Svelte 更新机制?
前言知乎上讨论挺 “疯狂” 的帖子,仅供参考!!!问题一个常年用react的人使用vue,第一感觉就是好贴心,好简单,移除了很多概念,轻松。而现在使用 svelte 重新拥有了这种感觉,而且更强烈。用了svelte之后,感觉他就是vue的优化版。移除了虚拟dom,放宽了模板编写的一些约束,typescript当前版本的兼容性也很好。有一种感觉,就是假设vue3不用考虑兼容vue2,那么把svelt
前言
知乎上讨论挺 “疯狂” 的帖子,仅供参考!!!
问题
一个常年用react的人使用vue,第一感觉就是好贴心,好简单,移除了很多概念,轻松。
而现在使用 svelte 重新拥有了这种感觉,而且更强烈。
用了svelte之后,感觉他就是vue的优化版。移除了虚拟dom,放宽了模板编写的一些约束,typescript当前版本的兼容性也很好。
有一种感觉,就是假设vue3不用考虑兼容vue2,那么把svelte改名为vue3就是心目中的vue3版本。
大伙怎么看?
一、你觉得 Svelte 有 Virtual DOM 吗?
这个问题可真是标题党,貌似 Svelte 没有 Virtual DOM 已经是共识了。的确,不较真的说, Svelte 就是没有 Virtual DOM。但是你要是说它绝对没有,那我告诉你这是不 可 能的。Virtual DOM 最核心的 Diff 算法体现在两个列表间的比对,通过 Diff 算法一顿捣鼓,最后捣鼓出了高效更新 DOM 的方案。我可以明确地告诉你,Svelte 在做两个列表间的更新时,也是需要一顿捣鼓的,它的 keyed each blocks 就相当于 Virtual DOM。你看看它源码里的 update_keyed_each() 函数:点此
里面的 oldblocks 和 newblocks 就相当于 Virtual DOM 里的 oldChildren 和 newChildren。这也是没有办法的,你在编译阶段几乎是不可能知道我将会对列表进行怎样的操作的。因此为了运行时高效,就必须做这一层 Diff。
二、编译到原生 DOM 比编译到 Virtual DOM 快?
朋友,喝假酒了吧,几个菜?比传统 Virtual DOM 快是肯定的,但你得知道传统 Virtual DOM 为什么慢?本根原因在于传统 Virtual DOM 当初就不是作为编译产物出现的,因此它无法区分动态和静态内容。试想一下,如果 Virtual DOM 本身是知道哪些是动态的,哪些是静态的,那它就不慢了呀。Svelte 快就快在编译时就区分了静态和动态内容,当更新的时候也只需要更新动态内容就可以了。但是谁规定 Virtual DOM 就不能区分动态和静态的内容了?Vue3 的 Virtual DOM 就可以呀。
三、Svelte 的更新机制你接受的了?
Svelte 的响应方案是采用一种 Bitmask-based change tracking 的机制配合赋值语句实现的。什么是 Bitmask-based change tracking ?说人话就是把变量进行编号,然后使用二进制位来存储变量是否为脏。当检测到你脚本中出现赋值语句时,调用 makeDirty 函数将变量标记为脏,然后开启刷新队列/入队更新操作,执行更新。但这有两个明显的问题:
- 基于赋值语句意味着阉割的响应能力,例如数组的 push/pop 之类的,delete obj.foo 之类的,总之除了赋值啥都不行
- 粒度不够细。即使都是赋值,也有问题,例如你有一个对象 obj,Svelte 只会给这个 obj 变量进行编号,并不会给 obj 对象下的属性编号,这意味着你给 obj.foo 赋值和给 obj.bar 赋值对 Svelte 来说是等价的操作。对于 Svelte 来说,它也不知道变量的值到底变没变。所以你会看到 Svelte 生成的真实代码中通常包含大量守卫代码,例如
你看,Svelte 在更新的时候,由于它根本不知道是不是真的有值发生变化。所以它除了需要使用位运算来判断你为哪个变量“赋值”了,还要检测值是否真的发生了变化。换句话说,即使你的模板中没有使用 obj.foo,但是模板中使用了 obj.bar,那么当你给 obj.foo 赋值时仍然会触发更新,Svelte 中通过 beforeUpdate 注册的钩子函数仍然会执行,即使实际上根本不需要更新任何内容。朋友你要知道,就这个操作在 Vue 中都算 bug 的。我现在有时候都在想,开发者的容忍能力一定是非常强的。不然怎么会有人能接受 Svelte 这种阉割的响应式方法。当然它这种基于位掩码的变化追踪,思路还是可以的,节省了内存占用。但我认为仍然有办法在内存和响应能力之间找到一个更完美一点的平衡点,而且我目前也正在思考这方面的事儿。另外生成大量的守卫代码,意味着你的 bundle size 随着页面中动态绑定的增加而增加。
四、Svelte 是 no runtime ?
这个咱们文明点说,就他妈是扯淡。我其实不知道官方有没有这样宣传过的,因为说实话我根本没用过 Svelte,平时也不关注,文档也只看了前两页。我对 Svelte 的理解都来自于它官网上的 Example,所以也不一定全都是正确地。但你要说它是 no runtime,这就很扯了。
上面提到的 update_keyed_each 函数是不是运行时?框架需要避免重复的更新 job 执行,就必须要实现一个 scheduler ,这是不是运行时?Transition 需不需要运行时?抽象一些原生的 DOM 操作是不是运行时?Svelte 也有声明周期,组件实例的概念,这些都需要抽象最基本的运行时实现。所以怎么就 no runtime 了?实际上你把 Vue3 用于支持 Virtual DOM 的代码去掉,剩下的代码也不见得比 Svelte 的运行时代码多多少。如果大家都到了拼运行时代码量的程度,那么基本就可以确定:运行时代码量少,等价于功能不全。
我在 Twitter 上见到过有人发文章,它的用词是“没有运行时系统”,你看这个就比 no runtime 要聪明的多。
更多推荐
所有评论(0)