虚拟dom和diff算法

626 阅读1分钟

重点:虚拟dom是虚拟的,只在概念里面存在,真实的是一个ast语法树


<template>
    <div id="123">
        <p><span class="234"></span></p>
        <p>111</p>
    </div>
</template>


以上代码解析为对象形式展示

var virtualDom = {
    dom:'div',
    props:{
        id:123
    },
    children:[
        {
            dom:"p",            props:{},
            children:[
                dom:"span",
                props:{
                    class:'234'
                },
                children:[]
            ]        },
       {
            dom:"p",            
            props:{},
            text:'111',
            children:[]       
        }    ]
}



diff算法比对流程

patchVnode(oldVnode,vnode){
    //获取真实dom
    const el = vnode.el = oldVnode.el
    //分别拿出旧节点的子元素和新节点的子元素
    let i, oldCh = oldVnode.children, ch = vnode.children
    //如果两个节点相同,没有发生更新的话,不做任何事情
    if (oldVnode === vnode) return
    
    //接下来分4种情况:只有文字节点,删除了子元素,增加子元素,子元素变动

    //判断旧的dom文字是否为空,新的dom文字是否为空,新旧dom的文字是否相同
    if (oldVnode.text !== null && vnode.text !== null && oldVnode.text !== vnode.text) {
        //单纯的文字节点
        //更新文字内容
        api.setTextContent(el, vnode.text)
    } else {
        //更新dom
        updateEl()
        //判断新旧节点子元素是否存在,是否发生改变
        if (oldCh && ch && oldCh !== ch) {
            //存在,并且发送变化
            //更新子元素
             updateChildren()
        } else if (ch) {
             //新节点有子元素,老节点没有子元素,所以需要创建新的子元素
             createEl(vnode)
        } else if (oldCh) {
            // 新节点没有子元素,老节点有子元素,所以需要删除老节点的子元素
            api.removeChildren(el)
        }
    }
}