Web前端学习之虚拟DOM如何进化为真实DOM
小职 2021-01-20 来源 :前端简报 阅读 1068 评论 0

摘要:本文主要向大家介绍了Web前端学习之虚拟DOM如何进化为真实DOM,通过具体的内容向大家展现,希望对大家Web前端的学习有所帮助。

本文主要向大家介绍了Web前端学习之虚拟DOM如何进化为真实DOM,通过具体的内容向大家展现,希望对大家Web前端的学习有所帮助。

Web前端学习之虚拟DOM如何进化为真实DOM

前言

 

Vue和React的Render函数中都涉及到了Virtual DOM的概念,Virtual DOM也是性能优化上的重要一环,同时突破了直接操作真实DOM的瓶颈,本文带着以下几个问题来阐述Virtual DOM。

 

1.为什么要操作虚拟 DOM?

 

2.什么是虚拟 DOM?

 

3.手把手教你实现虚拟 DOM 渲染真实 DOM

 

希望阅读本文之后,能够让你深入的了解虚拟 DOM并且在开发和面试中收益。

 

为什么要操作虚拟 DOM

 

为了帮助我们更好的理解为什么要操作虚拟 DOM,我们先从浏览器渲染[1]一个 HTML 文件需要做哪些事情说起:

 Web前端学习之虚拟DOM如何进化为真实DOM

 

浏览器渲染机制大致可以分为以下 5 步走:

 

1.创建 DOM tree

 

2.创建 Style Rules

 

3.构建 Render tree

 

4.布局 Layout

 

5.绘制 Painting

 

我们过去使用原生JavaScript和jquery去操作真实DOM的时候,浏览器会从构建 DOM� 开始从头到尾的执行一遍渲染的流程。

 

在一次开发中,假如产品告诉你一个需求,你需要在一次操作中更新10个DOM节点,理想状态是浏览器一次性构建完DOM树,再执行后续操作。但浏览器没这么智能,收到第一个更新 DOM 请求后,并不知道后续还有9次更新操作,因此会马上执行流程,最终执行 10 次流程。

 

过了一会产品经理把你叫过去和你说把需求改一下,此时你又需要操作一次 DOM 的更新,那么这个时候之前做的 10 次 DOM 操作就是白白浪费性能,浪费感情。

 

即使计算机硬件一直在更新迭代,但是操作DOM的代价仍旧是昂贵的,频繁操作 DOM 还是会出现页面卡顿,影响用户的体验。真实的 DOM 节点,哪怕一个最简单的 div 也包含着很多属性,可以打印出来直观感受一下:

 Web前端学习之虚拟DOM如何进化为真实DOM

 

如此多的属性,如果每次对 DOM 结构都进行更新,一次,两次,三次...一百次....一千次...,可想而知,是多么庞大的数据量。

 

因此虚拟DOM就是为了解决这个浏览器性能问题而被设计出来的。例如前面的例子,假如一次操作中有 10 次更新 DOM 的动作,虚拟DOM不会立即操作DOM,而是将这 10 次更新 DOM 的动作通过Diff算法最终生成一个js对象,然后通知浏览器去执行一次绘制工作,这样可以避免大量的无谓的计算量。

 

什么是虚拟 DOM

 

虚拟 DOM[2]就是我们上面所说的js对象。

 

其本质上就是在JS和DOM之间做了一个缓存。可以类比 CPU 和硬盘,既然硬盘这么慢,我们就在它们之间加个缓存:既然 DOM 这么慢,我们就在它们 JS 和 DOM 之间加个缓存。CPU(JS)只操作内存(Virtual DOM),最后的时候再把变更写入硬盘(DOM),直接操作内存中的 JS 对象的速度显然要更快。

 

function vnode(tag, data, key, children, text) {

    return {

        tag,

        data,

        key,

        children,

        text

    }

}

举个栗子:

 

假如我们有这样的一个 DOM 树

 

<ul>

  <li>前端简报</li>

  <li>vue</li>

</ul>

那么,我们怎么用 js 的对象来对应到这个树呢?

 

{

    tag: 'ul',        // 元素标签

    data: {           // 属性

        class: 'list'

    },

    key: '',

    text: '',  // 文本内容

    children: [

        {

            tag: "li",

            data: {

                class: "item"

            },

            key: '',

            text: '',

            children: [

                {

                    tag: undefined,

                    data: undefined,

                    key: undefined,

                    text: '前端简报',

                    children: []

                }

            ]

        },

        {

            tag: "li",

            data: "",

            key: '',

            text: '',

            children: [

                {

                    tag: undefined,

                    data: undefined,

                    key: undefined,

                    text: 'vue',

                    children: []

                }

            ]

        }

    ]       // 子元素

}

由此可知:DOM tree的信息都可以用JavaScript对象来表示,反过来,我们也可以用 JavaScript对象表示的树结构来构建一棵真正的DOM树。

 

实现虚拟 DOM 渲染真实 DOM

 

有了JavaScript对象之后如何转化为真实的 DOM 树结构呢?

 

ul 和 li 在 js 对象中,页面上并没有此结构,所以我们需要把ul和li转化为和

 

标签

 

而文本标签我们定义 Vnode 为:

 

{

   tag: undefined,

   data: undefined,

   key: undefined,

   text: 'vue',

   children: []

}

故可以判断tag的类型来确定创建元素的类型.

 

function createElm(vnode) {

    let { tag, data, children, key, text } = vnode;

 

    if (typeof tag == "string") {

        vnode.el = document.createElement(tag);  //创建元素放到vnode.el上

        children.forEach(child => {

            vnode.el.appendChild(createElm(child))

        })

    } else {

        vnode.el = document.createTextNode(text);  //创建文本

    }

    return vnode.el

}

如果子节点存在并且也是虚拟DOM的话,我们通过递归调用创建子节点。

 Web前端学习之虚拟DOM如何进化为真实DOM

 

创建 DOM 树结构之后我们需要设置节点的属性,即处理虚拟 DOM 中的data属性。

 

function updateProperties(vnode) {

    let el = vnode.el;

    let newProps = vnode.data || {};

    for (let key in newProps) {

        if (key == "style") {

            for (let styleName in newProps.style) {

                el.style[styleName] = newProps.style[styleName];

            }

        } else if (key == "class") {

            el.className = newProps.class;

        } else {

            el.setAttribute(key, newProps[key]);

        }

    }

}

在我们创建元素标签之后调用updateProperties方法即可

 Web前端学习之虚拟DOM如何进化为真实DOM

 

把上面创建出来的真实 DOM 结构 vnode.el 添加到文档当中即可呈现出我们需要的真实 DOM 结构

 

let parentElm = document.getElementById("app").parentNode; 获取之前app的父亲body

parentElm.insertBefore(createElm(vnode), document.getElementById("app").nextSibling); //body里在老的app后面插入真实dom

parentElm.removeChild(document.getElementById("app")); //删除老的节点

 Web前端学习之虚拟DOM如何进化为真实DOM

 

总结

 

以上就是本文的全部内容,我想我们现在应该了解什么是虚拟DOM的概念了以及虚拟DOM是如何实现真实DOM渲染的。其中用到了主要用到了子节点的递归。


关注“职坐标在线”(Zhizuobiao_Online)公众号,免费获取学习教程资料、技术就业咨询

Web前端学习之虚拟DOM如何进化为真实DOM

本文由 @小职 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程