虚拟Dom
栏目: JavaScript · 发布时间: 5年前
内容简介:## 什么是vdom ##用js来模拟上述办法遇到的问题
Virtual Dom
- vdom 是vue和react的核心
- vdom是什么东西,有什么用,为什么会存在vdom?
- vdom如何应用,核心API是什么?
- diff算法
## 什么是vdom ##
- 用js模拟DOM结构
- DOM变化的对比,放在JS层来做
- 提高重绘性能
<ul id="list"> <li class="item">Item 1</li> <li class="item">Item 2</li> </ul>
用js来模拟
{ tag:"ul", attrs:{ id:"list" }, children:[ { tag:"li", attrs:{ className: "item"}, //class是js的保留字,所以用className children:['Item 1'] },{ tag:"li", attrs:{ className: "item"}, children:['Item 2'] } ] }
设计一个需求场景,渲染一个数组成表格
//Jquery的实现 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.4.0/jquery.min.js"></script> <script type="text/javascript"> var dataList = [ { name:'111', age:1 },{ name:'222', age:2 },{ name:'333', age:3 },{ name:'444', age:4 }, ] $(document).ready(function () { function render(data){ var $container = $('#container') $container.html('') //拼接tabel $table = $('<table>') $table.append($('<tr><td>name</td><td>age</td></tr>')) //渲染到页面 data.forEach(item => { $table.append($(`<tr><td>${item.name}</td><td>${item.age}</td></tr>`)) }); $container.append($table) } render(dataList) $("#btn-change").click(function(){ dataList[1].age=30 //每次修改数据都会清空dom,然后重绘表格 render(dataList) }) }) </script> </head> <body> <div id="container"></div> <button id="btn-change">修改数据</button> </body> </html>
上述办法遇到的问题
- js原生或者是Jquery框架时代,都是直接操作DOM节点来进行渲染页面,可是这样的代价确实是很大,需要将原本的DOM全部清除,然后在重新渲染一遍
- 操作Dom非常昂贵。每个Dom自带了太多的属性。 js运行效率高
- 尽量减少Dom操作
- 项目越复杂,运行效率越低,影响越严重
- vdom 可以解决这个问题,将Dom操作方在Js层,提高效率
vdom如何应用,核心API
-
snabbdom
为什么是snabbdom.js
由于虚拟dom有那么多的好处而且现代前端框架中react和vue均不同程度的使用了虚拟dom的技术,因此通过一个简单的 库赖学习虚拟dom技术就十分必要了,至于为什么会选择snabbdom.js这个库呢?原因主要有两个:
源码简短,总体代码行数不超过500行。
著名的vue的虚拟dom实现也是参考了snabbdom.js的实现。
- 用snabbdomjs 实现上述例子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom.js"></script> <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-class.js"></script> <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-props.js"></script> <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-style.js"></script> <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-eventlisteners.js"></script> <script src="https://cdn.bootcss.com/snabbdom/0.7.1/h.min.js"></script> </head> <body> <div id="container"></div> <button id="btn-change">修改数据</button> <script type="text/javascript"> var snabbdom = window.snabbdom //定义patch var patch = snabbdom.init([ snabbdom_class, snabbdom_props, snabbdom_style, snabbdom_eventlisteners ]) var h = snabbdom.h var container = document.getElementById("container") //生成vnode var vnode= h('ul#list',{},[ h('li.item',{},'Item 1'), h('li.item',{},'Item 2') ]) patch(container,vnode) document.getElementById("btn-change").addEventListener('click',function(){ console.log("111") var newVnode = h('ul#list',{},[ h('li.item',{},'Item 1'), h('li.item',{},'Item B'), h('li.item',{},'Item 3') ]) patch(vnode,newVnode) }) </script> </body> </html>
//修改数据只是修改了 第二个item 第三,第一个数据没变化(F12查看Element 第一个item没有闪烁)
diff算法
- 什么是diff算法
- 去繁就简
- vdom 为何用diff算法
- diff算法的实现流程
diff命令是 linux 系统自带的基础命令
git diff 判断文本文件哪里被修改了
diff算法一直都在,并不是因为react、vue才出现的
vdom为何使用diff算法
- DOM 操作是昂贵的,因此尽量减少DOM操作
- 找出本次DOM必须更新的节点来更新,其他的不更新
- 这个找出的过程,就需要diff算法
diff实现过程
只需要明白
- path(container,vnode)
- path(vnode,newnode)
通过VNode创建一个真实的DOM的流程
function createElement(vnode){ var tag= vnode.tag var attrs = vnode.attrs||{} var children = vnode.children || [] if(!tag){ return null } var elem = document.createElement(tag) var attrName for(attrName in attrs){ if(attrs.hasOwnProperty(attrName)){ elem.setAttribute(attrName,attrs[attrName]) } } children.forEach(childNode => { elem.appendChild(createElement(childNode)) }); //返回真实的Dom return elem }
path(vnode,newVnode) 的实现,
function updateChildren(vnode,newVnode){ var children = vnode.children || [] var newChildren = newVnode.children || [] //遍历现有的children children.forEach((child,index )=> { var newChild = newChildren[index] if(newChild == null){ return } if(child.tag === newChild.tag){ updateChildren(child,newChild) }else{ replaceNode(child,newChild) } }); } function replaceNode(vnode,newVnode){ var elem = vnode.elem var newElem = createElement(newVnode) }
不仅仅是以上的内容,还有以下的内容
- 节点新增和删除
- 节点重新排序
- 节点属性、样式、事件绑定
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- VMware虚拟机嵌套部署KVM虚拟机指南
- 虚拟化生态系统及实现从虚拟化走向云端
- 如何探测虚拟化环境是物理机、虚拟机还是容器?
- 如何探测虚拟化环境是物理机、虚拟机还是容器?
- 【Java虚拟机规范】Java虚拟机结构:运行时数据区
- 像虚拟机一样虚拟数据,开源项目Alluxio要发力中国市场
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTML5与CSS3权威指南(上册) (第3版)
陆凌牛 / 机械工业出版社 / 2015-9-1 / CNY 89.00
本书是HTML 5与CSS 3领域公认的标杆之作,被读者誉为“系统学习HTML 5与CSS 3的最佳著作”和“Web前端工程师案头必备图书之_”。 前两版累计印刷超过15次,网络书店评论超过8000条,98%以上的评论都是五星级的好评。不仅是HTML 5与CSS 3图书领域当之无愧的领头羊,而且在整个原创计算机图书领域是佼佼者。 第3版首先从技术的角度根据最新的HTML 5和CSS 3......一起来看看 《HTML5与CSS3权威指南(上册) (第3版)》 这本书的介绍吧!