Virtual-DOM的理解

Virtual-DOM的理解

什么是DOM?

在说Virtual-DOM以前,咱们来先说下什么是DOM,DOM从字面上来理解是文档对象模型。vue

W3C对DOM的定义是:“一个与系统平台和编程语言无关的接口,程序和脚本能够经过这个接口动态地访问和修改文档内容、结构和样式。”node

而从上面的定义总结来看,DOM是接口,这个接口能够操做文档。react

而文档呢就是Document,在HTML中的Document,能够简单理解成一个节点树,而咱们要将这个节点树映射成对象,而对象中天然就存在属性和方法了,其中这些方法就让咱们能够操做文档(好像说的仍是有点绕)git

什么是Virtual-DOM?

Virtual-DOM翻译过来就是虚拟DOM,而它其实能够简单理解为,经过JS去建立的表示DOM的对象,而且未加载到真实页面中github

  • virtual-dom = js对象
  • 未渲染到页面中

有人说用virtual-dom比真实dom快,其实这是相对的,virtual-dom不少时候都不是最优的操做,但它具备普适性,在效率、可维护性之间达平衡算法

在网上看到一段代码,比较简洁的描述了如何去建立一个virtual-dom:编程

//创建一个VNode的对象
class VNode {
    constructor(tag, children, text) {
        this.tag = tag
        this.text = text
        this.children = children
    }

    render() {
        if (this.tag === '#text') {
            return document.createTextNode(this.text)
        }
        let el = document.createElement(this.tag)
        this.children.forEach(vChild => {
            el.appendChild(vChild.render())
        })
        return el
    }
}

function v(tag, children, text) {
    if (typeof children === 'string') {
        text = children
        children = []
    }
    return new VNode(tag, children, text)
}

/* let nodesData = { tag: 'div', children: [ { tag: 'p', children: [ { tag: 'span', children: [ { tag: '#text', text: 'baidu' } ] } ] }, { tag: 'span', children: [ { tag: '#text', text: 'alibaba' } ] } ] } */

let vNodes = v('div', [
    v('p', [
        v('span', [v('#text', 'baidu')])
    ]
    ),
    v('span', [
        v('#text', 'alibaba')
    ])
]);
console.log(vNodes.render())//创建真实DOM

// 对比DOM树变动
function patchElement(parent, newVNode, oldVNode, index = 0) {
    if (!oldVNode) {
        parent.appendChild(newVNode.render())
    } else if (!newVNode) {
        parent.removeChild(parent.childNodes[index])
    } else if (newVNode.tag !== oldVNode.tag || newVNode.text !== oldVNode.text) {
        parent.replaceChild(newVNode.render(), parent.childNodes[index])
    } else {
        for (let i = 0; i < newVNode.children.length || i < oldVNode.children.length; i++) {
            patchElement(parent.childNodes[index], newVNode.children[i], oldVNode.children[i], i)
        }
    }
}


let vNodes1 = v('div', [
    v('p', [
        v('span', [v('#text', 'baidu')])
    ]
    ),
    v('span', [
        v('#text', 'ali')
    ])
]
)//虚拟DOM1

let vNodes2 = v('div', [
    v('p', [
        v('span', [
            v('#text', 'jd')
        ])
    ]
    ),
    v('span', [
        v('#text', 'baidu'),
        v('#text', 'map')
    ])
]
)//虚拟DOM2
const root = document.querySelector('#root')
patchElement(root, vNodes1) //对比更新
复制代码

咱们从上面的代码能够清晰的看到 vdom的简单流程app

vue2引入的vdom是基于snabbdom进行的修改而来,对于snabbdom的源码解析,咱们能够看这里dom

react的diff算法,在16版本以前,与vue2应该大同小异 而在react16以后的fiber,采用了不一样的方式编程语言

上面只是简单的介绍了下virtual-dom的概念而已,而对于具体究竟是如何进行vdom之间的diff,才是更核心的东西,咱们后续再去研究它

更多内容请看 blog

相关文章
相关标签/搜索