设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 重新 试卷 文件
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

2019 JSConf.Asia尤雨溪:在框架设计中寻求平衡(5)

发布时间:2019-08-05 12:06 所属栏目:21 来源:qiangdada
导读:因此,对于生产用例来说,最有可能的情况是你需要用户事先编译,这样对于构建步骤来说是一个硬性要求,这是不可避免的,要么在运行中进行编译,要么在预构建中进行编译,其中涉及我们现在或多或少习惯的所有node.js

因此,对于生产用例来说,最有可能的情况是你需要用户事先编译,这样对于构建步骤来说是一个硬性要求,这是不可避免的,要么在运行中进行编译,要么在预构建中进行编译,其中涉及我们现在或多或少习惯的所有node.js工具链。但如果你能避免的话,对于初学者来说是件好事。

OK,因此,Vue 又一次夹在中间,我想再次强调,这不是说 Vue 是最好的。

「2019 JSConf.Asia - 尤雨溪」在框架设计中寻求平衡,深度好文

但是,Vue 的渲染机制独特之处在于,如果你真的将模板结合到 VDOM 中,那么我们可以同时拥有 VDOM 和模板编译。

「2019 JSConf.Asia - 尤雨溪」在框架设计中寻求平衡,深度好文

所以我们可以充分利用这两点。

「2019 JSConf.Asia - 尤雨溪」在框架设计中寻求平衡,深度好文

我们有做过性能测试:在编译步骤中产生的特别优化,我们不做渲染功能,稍后我将详细介绍这一点。

在 vue2.x 版本,我们实际上还没有充分利用这个机会,当前 vue 2.x 中的 VDOM 性能这块表现平平。

但我会谈下 3.0 对这点所做的事,让它可以更快。

还有表现力,你可以跳过模板层直接进入渲染函数,直接利用JavaScript来执行任意复杂的逻辑。

因此,当你感觉自己受到模板约束时,这会为你提供一条出路。

缺点是,尽管我们现在确实很快,我们可能永远不会比 SVELTE 感觉起来快。因为 SVELTE 的输出是最普通的 JavaScript。然而,为了兼容手写的渲染函数,Vue 仍然需要维护 VDOM,这样一来常量则必不可少。另一方面,它也会产生分歧,即我到底应该使用哪一种方式?

因此,很多用户虽然可以使用渲染函数,但他们可能从未使用过它。

现在让我们把它放到我们通过文件做的事情上,将 Vue 的模板编译成 VDOM,其运行速度比普通的 VDOM 要快。

「2019 JSConf.Asia - 尤雨溪」在框架设计中寻求平衡,深度好文

这就是我们刚才已经讨论过的,这个模板只有一个节点会改变。理想状态下我们只需直接更新 message 字符串,节点结构是静态的,并且从来不会发生变化,只有一个动态节点。

所以,如果我们研究这个模板可以看出它是个非常简单的例子。

「2019 JSConf.Asia - 尤雨溪」在框架设计中寻求平衡,深度好文

当我们有类似于 v-if 这样的东西时,它会变得有点复杂,我们称之为 JSX 中的结构指令,它相当于是根据条件返回不同结果判断的三元表达式。

现在,这会创建一个动态节点结构,因为该节点可能存在或可能不存在。

为了处理这种简单的 VDOM Diff 算法,假设节点列表已经改变,那么我们需要对两个子数组进行 Diff 操作。

但是如果我们尝试将其拆分,会看到 v-if 将模板拆分为两个嵌套块。

「2019 JSConf.Asia - 尤雨溪」在框架设计中寻求平衡,深度好文

我们来思考一下,如果将 v-if 本身看作一个节点,外部块则会有一个静态节点内容、节点结构。

在 v-if 内部,它也是静态的。我们有两个静态块,在每个块内,你无需对节点顺序进行 Diff 操作,你唯一要做就是这个块内部进行数组的扁平化操作。

同理,对于每个 v-for 迭代我们也可以将其看成一个静态块。

因此,如果你有更多像 v-if 、内嵌 v-for 的写法,你只是在进一步将代码拆分成嵌套块。

「2019 JSConf.Asia - 尤雨溪」在框架设计中寻求平衡,深度好文

所以,我们最终得到一种我称之为 Block Tree(区块树)的东西,这只是一种玩法。

「2019 JSConf.Asia - 尤雨溪」在框架设计中寻求平衡,深度好文

但 Block Tree 是一个嵌套块的块列表,因为每个块中都有一个完全静态的节点结构,所有没有必要使用递归到下层去对子列表进行 Diff 操作。

在每个块中,你只有一个单一扁平化数组节点可能会发生改变,我们还提供了其它组织上的提示。例如,如果一个节点只有一个动态 class 绑定,我们有条捷径,即你只需直接设置 class,然后就可以继续执行,而不必对 Props 进行 Diff 操作。

所以,对于同一模板的 Diff,vue2.x 版本和 vue3.x 版本的做法会有明显的区别。vue2.x 版本我们需要做一个完整的 Diff 操作,vue3.x 版本我们就只需通过使用一个单一扁平化数组(包含一个动态文本节点),而你唯一需要做的事情就是比较文本是否发生了改变。

对此,我们做了一个简单的基准测试(benchmark), 做 1000 个 v-for 列表迭代,每个块有 12 个 dom 节点,总共 12000 个 dom 节点,每次迭代都会动态绑定一些类或者文本。

然后我们在页面上做了 4000 个动态绑定,然后对其更新。我们做了 100 次运行,在目前 2.6 的版本,更新时间要 36ms,而在目前 3.0 的版本中,使用新的编译策略,只需要大概 5.4ms,比之前快了6倍多。

「2019 JSConf.Asia - 尤雨溪」在框架设计中寻求平衡,深度好文

注意,(数据)仅限于这个基准测试。真实的应用中你可能会有一个不同的数字,但或多或少,它都会更快,这是一个基准。

五、状态

然后,在状态机制这块,我可能没有时间去真正深入研究这个问题,它可能会是另外一个演讲的话题。

「2019 JSConf.Asia - 尤雨溪」在框架设计中寻求平衡,深度好文

六、总结

但是还是总结一下,当你试图去设计一个框架时,最佳平衡点在哪?

或许这个问题应该重新表述下。是否存在一个完美的平衡点?它又是否是一个单一的完美的平衡点,甚至是以 JS 开发人员作为一个整体的最佳平衡点?

因为像我们所有人一样,都在努力去优化我们正在构建的一些特定又不同的东西。

比如说 SVELTE,它的优势在于当你构建一些小的东西时,它可以产出非常轻量级的代码。它也非常快,消耗内存也非常少,所以它甚至可以像嵌入式设备一样使用。

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读