前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计一个虚拟Dom,其实没那么难!

设计一个虚拟Dom,其实没那么难!

作者头像
JowayYoung
发布2021-07-05 18:11:06
6040
发布2021-07-05 18:11:06
举报
文章被收录于专栏:JowayYoung谈前端JowayYoung谈前端

老陈发现从17年开始一些响应式的框架就越来越火,之前在读书的时候就觉得这玩意肯定能火,16年就有简单的使用。然后,最近一次小面试问到了如何设计一个虚拟dom,就简单说了是一个dom映射在js对象里面的东西,感觉还是不够深入。所以有了现在这篇文章啦。

一、前端应用的数据状态管理

假设,我们有一个应用,应用里面有一个数据表,数据表会根据某个字段进行升序或者降序排序展示,这个跟数据库表很像哈,那么我们怎么在页面显示出来呢?

我们顺着自己的逻辑来:

我们设定一个字段名,设定一个升序或者降序的标识,然后通过点击之后,对对象进行排序,再利用js插入页面更新视图。

其实这么做你会发现一个问题,我们要维护的字段特别多,那么点击事件和更新视图的操作就会越来越多。所以我们发现出现了MVC、MVP的架构模式,这只能解决一部分问题,代码组织维护的问题,不能减少操作DOM的次数,该操作还是得操作。

所以那么多的问题,怎么解决呢?我们需要做一个东西,可以让视图和状态绑定,状态变更了视图就自动变更。我们就不需要手动去更新页面。 就是MVVM就呼之欲出了。

只要在模板中声明视图组件是和什么状态进行绑定的,双向绑定引擎就会在状态更新的时候自动更新视图。

他其实解决的是状态维护的问题,大大减少了代码中的视图更新逻辑,但是这不是唯一的办法,还有一个简单粗暴的办法可以大大降低视图更新的操作,一旦状态发生变化,就用模板引擎重新渲染整个视图,替换掉旧的视图,只要用户触发点击事件就更新状态,这样也不需要手动操作DOM了。

innerHTML就完事,这样做就是有一个很不好的弊端,频繁操作DOM,会使性能大大降低,这样的性能成本实在是太高了。

这时候,虚拟DOM可以出现了。

二、Virtual DOM算法

DOM特别慢,记住他,一个div的元素上面就附带着各种各样的属性值,如果你操作可能就会触发页面重排,这就是性能一直被吐槽的原因。

如果是JS的对象,处理起来会更简单,我们可以将DOM树上的结构,属性都用JS表示出来。

代码语言:javascript
复制
let element = {
 tagNmae: 'div', //节点标枪
 props: {
   id: 'items'
 },
 children: [
  {tagName: 'div', props: {class: 'item'}, children: ["Item 1"]},
  {tagName: 'div', props: {class: 'item'}, children: ["Item 2"]},
  {tagName: 'div', props: {class: 'item'}, children: ["Item 3"]},
 ]
}
代码语言:javascript
复制
<div id="items">
  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
</div>

可以仔细看一下上面两个对应关系,我们可以用JS对象表示的树来构建一颗真正的DOM树。

到这,你有没有发现我们都在做无用功,一个JS对象来构建DOM树,重新渲染这个JS对象,该更新还是得更新,搞毛呀。

所以,我们需要对这个树进行一些特殊的操作,就是将新树和旧树进行对比,这样我们到真正对页面进行DOM操作就只会变更需要变更的东西。这一步就是所谓的虚拟DOM算法。

我们可以给虚拟DOM下结论,他其实就是给JS操作和DOM之间加一层,用于对比,虚拟DOM是DOM的一个映射。

三、diff算法

比较两个树的差异是虚拟DOM算法最核心的部分,所谓虚拟DOM的两个树之间的diff是一个时间复杂度为O(n^3)的问题,但是在前端,我们只会对同一层进行对比也就是O(n)的时间复杂度。

主要要设计一个虚拟的DOM的话要有三个步骤,第一个是一个DOM到虚拟DOM的映射对象,第二个是diff算法的设计,第三对存在差异的部分进行DOM操作。

看到这里,你应该对虚拟DOM有所了解了,有点标题党了,如果大家有兴趣我在把写好的虚拟DOM部分的源码分享出来。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-06-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IQ前端 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档