摘要:不同的框架对这三个属性的命名会有点差别,但表达的意思是一致的。它们分别是标签名属性和子元素对象。我们先来看下页面的更新一般会经过几个阶段。元素有可能是数组的形式,需要将数组解构一层。
欢迎关注我的公众号睿Talk,获取我最新的文章:
目前最流行的两大前端框架,React和Vue,都不约而同的借助Virtual DOM技术提高页面的渲染效率。那么,什么是Virtual DOM?它是通过什么方式去提升页面渲染效率的呢?本系列文章会详细讲解Virtual DOM的创建过程,并实现一个简单的Diff算法来更新页面。本文的内容脱离于任何的前端框架,只讲最纯粹的Virtual DOM。敲单词太累了,下文Virtual DOM一律用VD表示。
这是VD系列文章的开篇,以下是本系列其它文章的传送门:
你不知道的Virtual DOM(一):Virtual Dom介绍
你不知道的Virtual DOM(二):Virtual Dom的更新
你不知道的Virtual DOM(三):Virtual Dom更新优化
你不知道的Virtual DOM(四):key的作用
你不知道的Virtual DOM(五):自定义组件
你不知道的Virtual DOM(六):事件处理&异步更新
本质上来说,VD只是一个简单的JS对象,并且最少包含tag、props和children三个属性。不同的框架对这三个属性的命名会有点差别,但表达的意思是一致的。它们分别是标签名(tag)、属性(props)和子元素对象(children)。下面是一个典型的VD对象例子:
{ tag: "div", props: {}, children: [ "Hello World", { tag: "ul", props: {}, children: [{ tag: "li", props: { id: 1, class: "li-1" }, children: ["第", 1] }] } ] }
VD跟dom对象有一一对应的关系,上面的VD是由以下的HTML生成的
Hello World
- 第1
一个dom对象,比如li,由tag(li), props({id: 1, class: "li-1"})和children(["第", 1])三个属性来描述。
三、为什么需要VDVD 最大的特点是将页面的状态抽象为 JS 对象的形式,配合不同的渲染工具,使跨平台渲染成为可能。如 React 就借助 VD 实现了服务端渲染、浏览器渲染和移动端渲染等功能。
此外,在进行页面更新的时候,借助VD,DOM 元素的改变可以在内存中进行比较,再结合框架的事务机制将多次比较的结果合并后一次性更新到页面,从而有效地减少页面渲染的次数,提高渲染效率。我们先来看下页面的更新一般会经过几个阶段。
从上面的例子中,可以看出页面的呈现会分以下3个阶段:
JS计算
生成渲染树
绘制页面
这个例子里面,JS计算用了691毫秒,生成渲染树578毫秒,绘制73毫秒。如果能有效的减少生成渲染树和绘制所花的时间,更新页面的效率也会随之提高。
通过VD的比较,我们可以将多个操作合并成一个批量的操作,从而减少dom重排的次数,进而缩短了生成渲染树和绘制所花的时间。至于如何基于VD更有效率的更新dom,是一个很有趣的话题,日后有机会将另写一篇文章介绍。
我们先从如何生成VD说起。借助JSX编译器,可以将文件中的HTML转化成函数的形式,然后再利用这个函数生成VD。看下面这个例子:
function render() { return (Hello World); }
- 第1
这个函数经过JSX编译后,会输出下面的内容:
function render() { return h( "div", null, "Hello World", h( "ul", null, h( "li", { id: "1", "class": "li-1" }, "u7B2C1" ) ) ); }
这里的h是一个函数,可以起任意的名字。这个名字通过babel进行配置:
// .babelrc文件 { "plugins": [ ["transform-react-jsx", { "pragma": "h" // 这里可配置任意的名称 }] ] }
接下来,我们只需要定义h函数,就能构造出VD
function flatten(arr) { return [].concat.apply([], arr); } function h(tag, props, ...children) { return { tag, props: props || {}, children: flatten(children) || [] }; }
h函数会传入三个或以上的参数,前两个参数一个是标签名,一个是属性对象,从第三个参数开始的其它参数都是children。children元素有可能是数组的形式,需要将数组解构一层。比如:
function render() { return (
继续之前的例子。执行h函数后,最终会得到如下的VD对象:
{ tag: "div", props: {}, children: [ "Hello World", { tag: "ul", props: {}, children: [{ tag: "li", props: { id: 1, class: "li-1" }, children: ["第", 1] }] } ] }
下一步,通过遍历VD对象,生成真实的dom
// 创建dom元素 function createElement(vdom) { // 如果vdom是字符串或者数字类型,则创建文本节点,比如“Hello World” if (typeof vdom === "string" || typeof vdom === "number") { return doc.createTextNode(vdom); } const {tag, props, children} = vdom; // 1. 创建元素 const element = doc.createElement(tag); // 2. 属性赋值 setProps(element, props); // 3. 创建子元素 // appendChild在执行的时候,会检查当前的this是不是dom对象,因此要bind一下 children.map(createElement) .forEach(element.appendChild.bind(element)); return element; } // 属性赋值 function setProps(element, props) { for (let key in props) { element.setAttribute(key, props[key]); } }
createElement函数执行完后,dom元素就创建完并展示到页面上了(页面比较丑,不要介意...)。
五、总结本文介绍了VD的基本概念,并讲解了如何利用JSX编译HTML标签,然后生成VD,进而创建真实dom的过程。下一篇文章将会实现一个简单的VD Diff算法,找出2个VD的差异并将更新的元素映射到dom中去:你不知道的Virtual DOM(二):Virtual Dom的更新
P.S.: 想看完整代码见这里,如果有必要建一个仓库的话请留言给我:代码
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/96981.html
摘要:变化的只有种更新和删除。页面的元素的数量随着而变。四总结本文详细介绍如何实现一个简单的算法,再根据计算出的差异去更新真实的。 欢迎关注我的公众号睿Talk,获取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、前言 目前最流行的两大前端框架,React 和 Vue,都不约而同的借助 Virtual DOM 技术提高页面的渲染...
摘要:最后里面没有第四个元素了,才会把苹果从移除。四总结本文基于上一个版本的代码,加入了对唯一标识的支持,很好的提高了更新数组元素的效率。 欢迎关注我的公众号睿Talk,获取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、前言 目前最流行的两大前端框架,React和Vue,都不约而同的借助Virtual DOM技术提高页面的渲染...
摘要:如果列表是空的,则存入组件后将异步刷新任务加入到事件循环当中。四总结本文基于上一个版本的代码,加入了事件处理功能,同时通过异步刷新的方法提高了渲染效率。 欢迎关注我的公众号睿Talk,获取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、前言 目前最流行的两大前端框架,React和Vue,都不约而同的借助Virtual DO...
摘要:现在流行的前端框架都支持自定义组件,组件化开发已经成为提高前端开发效率的银弹。二对自定义组件的支持要想正确的渲染组件,第一步就是要告诉某个标签是自定义组件。下面的例子里,就是一个自定义组件。解决了识别自定义标签的问题,下一步就是定义标签了。 欢迎关注我的公众号睿Talk,获取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、...
摘要:经过这次优化,计算的时间快了那么几毫秒。基于当前这个版本的代码还能做怎样的优化呢,请看下一篇的内容你不知道的四的作用。 欢迎关注我的公众号睿Talk,获取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、前言 目前最流行的两大前端框架,React和Vue,都不约而同的借助Virtual DOM技术提高页面的渲染效率。那么,什...
阅读 817·2021-10-25 09:48
阅读 609·2021-08-23 09:45
阅读 2495·2019-08-30 15:53
阅读 1757·2019-08-30 12:45
阅读 584·2019-08-29 17:21
阅读 3404·2019-08-27 10:56
阅读 2544·2019-08-26 13:48
阅读 688·2019-08-26 12:24