虛擬dom應用

vdom如何應用,核心api是什麼
一、介紹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模擬的體量很是小。css

 

看snabbdom裏面的介紹。一個h函數,一個patch函數,就是vdom最主要的api。看h函數傳的是什麼。html

第一個是標籤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閃爍了vue



二、重作以前的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。node



三、核心api
  h('<標籤名>', {...屬性}, [...子元素])
  h('<標籤名>', {...屬性}, '...')
 
  patch(container, vnode)
  patch(vnode, newVnode)
相關文章
相關標籤/搜索