virtual dom(vdom)--虚拟DOM

vdom

全名 virtual dom,虚拟dom,简称vdom
定义

  • 用js模拟dom结构
  • Dom变化的对比,放在js层来处理

好处

  • 提高重绘性能
  • DOM操作比较占内存,将dom操作放在js层,可以提高效率性能

vdom-snabbdom

实现vdom的插件,可以在bootcdn.cn中下载(代码中有引入)

核心API
h(‘标签名’, {…属性…}, […子元素…]);----子元素有多个,再使用 h(…)嵌套
h(‘标签名’, {…属性…}, ‘标签的text’)

// html写法

<ul id="ulList">
      <li>我是li</li>
</ul>
// 虚拟dom-snabbdom写法
h('ul#ulList',{},[
     h('li',{},'我是li')
])

初次渲染
patch(container,vnode); // container真实存在的空dom节点
再次渲染,只渲染数据改变部分
path(vnode, newVnode); //newVnode变更的数据源

代码示例
需求:实现按钮点击,更改列表数据
*vdom只修改改变的数据,无改变的数据,dom不变
*点击btn时,可以展开dom结构,可以看到那些节点变更了

<!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>Vdom</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:"21",
               address:"北京"
            },
            {
               name:"张三",
               age:"21",
               address:"北京"
            },
            {
               name:"张三",
               age:"21",
               address:"北京"
            }
        ];
        // 表头也放在data
        data.unshift({
            name:"姓名",
            age:"年龄",
            address:"地址"
        })
        var container = document.getElementById("container");
        // 生成vnode
        var vnode
        function render(data){
            var newVnode = h("table", {}, data.map(function(item){
                var tds = [];
                var i;
                for(i in item){
                    // 判断i是不是自有属性,非原型属性
                    if(item.hasOwnProperty(i)){
                        // item[i]+""  表示转换为字符串
                        tds.push(h("td", {}, item[i] + ""))
                    }
                }
                return h("tr", {}, tds)
            }));

            if (vnode) {
                // 改变
                patch(vnode, newVnode);
            } else {
                // 初次渲染
                patch(container, newVnode);
            }  
            // 赋值
            vnode = newVnode;
        }
        // 初次渲染
        render(data);

        // btn点击事件
        document.getElementById("btn-change").addEventListener("click",function(){
            data[1].age = 30;
            data[2].address = "深圳";
            render(data);
        })
    </script>

    
</body>
</html>

附带github介绍(看完上面的例子,这个就很容易看懂了)

var snabbdom = require('snabbdom');
// 定义patch
var patch = snabbdom.init([ // Init patch function with chosen modules
  require('snabbdom/modules/class').default, // makes it easy to toggle classes
  require('snabbdom/modules/props').default, // for setting properties on DOM elements
  require('snabbdom/modules/style').default, // handles styling on elements with support for animations
  require('snabbdom/modules/eventlisteners').default, // attaches event listeners
]);
// 定义h
var h = require('snabbdom/h').default; // helper function for creating vnodes

var container = document.getElementById('container');

/*
解释
div id-container,有两个class-two,classes, 
有一个点击事件someFn
第一个子节点span, 设置加粗样式,text是"This is bold"
第二个子节点是一个字符串
第三个子节点是a标签,有个href属性,指向"/foo",a的text是'I\'ll take you places!'
*/
var vnode = h('div#container.two.classes', {on: {click: someFn}}, [
  h('span', {style: {fontWeight: 'bold'}}, 'This is bold'),
  ' and this is just normal text',
  h('a', {props: {href: '/foo'}}, 'I\'ll take you places!')
]);
// 初次渲染:Patch into empty DOM element – this modifies the DOM as a side effect
patch(container, vnode);

var newVnode = h('div#container.two.classes', {on: {click: anotherEventHandler}}, [
  h('span', {style: {fontWeight: 'normal', fontStyle: 'italic'}}, 'This is now italic type'),
  ' and this is still just normal text',
  h('a', {props: {href: '/bar'}}, 'I\'ll take you places!')
]);
// 二次渲染:Second `patch` invocation
patch(vnode, newVnode); // Snabbdom efficiently updates the old view to the new state
发布了18 篇原创文章 · 获赞 0 · 访问量 380

猜你喜欢

转载自blog.csdn.net/sinat_41904410/article/details/99703021