虚拟dom应用

匿名 (未验证) 提交于 2019-12-02 23:43:01
vdom如何应用,核心api是什么
1、介绍snabbdom(开源社区用的多,vue2用的是他)
首先回顾下之前的vdom格式
真实的dom
<body>   <ul id="list">     <li class="item">item 1</li>     <li class="item">item 2</li>   </ul> </body>

js模拟的dom
{   tag: 'ul',   attrs: {     id: 'list'   },   children:[{     tag: 'li',     attrs: { className: 'item' },     children: ['item 1']   },{     tag: 'li',     attrs: { className: 'item'},     children:['item 2']   }] }

用js模拟的体量非常小。

看snabbdom里面的介绍。一个h函数,一个patch函数,就是vdom最主要的api。看h函数传的是什么。

第一个是标签div,标签对应的id #container,标签对应的class,two,classes。
第二个参数是,这个标签绑定了一个事件,函数叫someFn。
第三个是个数组,数组又是h函数,传入标签,属性,文本
第一次渲染是全部渲染到浏览器中,第二次渲染,数据源有所改变,根据改变重新生成一个newVnode,这个时候再patch。这个时候patch的时候,会进行一个对比,这个对比是只找出需要更新的那部分来更新

上面例子的模拟
<!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>   </head>   <body>     <div id="container"></div>     <button id="btn-change">change</button>      <!-- 这里版本要一致 -->     <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom.js"></script>     <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-class.js"></script>     <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-props.js"></script>     <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-style.js"></script>     <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-eventlisteners.js"></script>     <script src="https://cdn.bootcss.com/snabbdom/0.7.3/h.js"></script>      <script>       var snabbdom = window.snabbdom;         // 定义patch       var patch = snabbdom.init([         snabbdom_class,         snabbdom_props,         snabbdom_style,         snabbdom_eventlisteners       ])         // 定义h       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);        //模拟改变       var btnChange = document.getElementById('btn-change');       btnChange.addEventListener('click', function(){         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>

item1没有渲染,item b, item3闪烁了



2、重做之前的demo

<!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> </head> <body>   <div id="container"></div>   <button id="btn-change">change</button>     <!-- 这里版本要一致 -->   <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom.js"></script>   <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-class.js"></script>   <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-props.js"></script>   <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-style.js"></script>   <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-eventlisteners.js"></script>   <script src="https://cdn.bootcss.com/snabbdom/0.7.3/h.js"></script>    <script>     var snabbdom = window.snabbdom;      // 定义patch     var patch = snabbdom.init([       snabbdom_class,       snabbdom_props,       snabbdom_style,       snabbdom_eventlisteners     ])       // 定义h     var h = snabbdom.h;      // 将该数据展示成一个表格。然后随便修改一个信息,表格也跟着修改     var data = [{       name: '张三',       age: '20',       address: '北京'     },{       name: '李四',       age: '21',       address: '上海'     },{       name: '王五',       age: '22',       address: '广州'     }];       data.unshift({       name: '姓名',       age: '年龄',       address: '地址'     });      var container = document.getElementById('container');     var btnChange = document.getElementById('btn-change');       // 渲染函数     var vnode;     function render(data) {       var newVnode = h('table',{}, data.map(function(item){         var tds = [];         for (i in item){           if(item.hasOwnProperty(i)){             tds.push(h('td', {}, item[i]+''))           }         }         return h('tr',{}, tds);       }));        if (vnode) {         // re-render         patch(vnode, newVnode);       } else {         // 初次渲染         patch(container, newVnode);       }        vnode = newVnode;     }     render(data);      btnChange.addEventListener('click', function(){       data[1].age = 30;       data[2].address = '深圳';       // re-render       render(data);     })   </script> </body> </html>

再查看dom,不再是整个table渲染。就只更新改变的dom。



3、核心api
  h('<标签名>', {...属性}, [...子元素])
  h('<标签名>', {...属性}, '...')
  patch(container, vnode)
  patch(vnode, newVnode)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!