1. virtual DOM
一个真正的dom节点可以在js中映射成一个这样的对象,也就是js中的虚拟dom。
const node={
tag: 'ul',
attributes: {
id: 'list1',
class: ['classname1', classname2'],
...
},
chirldren: [child1, child2, child3,...]
}
我们在创建一个vue实例之后,它会先被render function
渲染成虚拟dom,然后再mount
到真正dom上。
1.1 .el
vue实例的el
可以是一个string
字符串或者是一个HTMLElement
.
1.2 virtual dom -- diff
function patch (oldVnode, Vnode){
if (sameVnode(oldVnode,Vnode) {
patchVnode(oldVnode, Vnode)
} else {
const oEl = oldVnode.el
let parentEle = api.parentNode(oEl)
createEle(vnode)
if (parentEle !== null) {
api.insertBefore(parentEle, vnode.el, api.nextSibling(oEl))
api.removeChild(parentEle, oldVnode.el)
oldVnode = null
}
}
}
sameVnode
的函数返回结果如果为true
,表示dom元素可以复用;如果为false
,则会生成新的dom元素,替换原来的dom元素。在dom元素可以复用的情况下,会进入patchVnode
函数:
patchVnode (oldVnode, vnode) {
const el = vnode.el = oldVnode.el
let i, oldCh = oldVnode.children, ch = vnode.children
if (oldVnode === vnode) return
if (oldVnode.text !== null && vnode.text !== null && oldVnode.text !== vnode.text) {
api.setTextContent(el, vnode.text)
}else {
updateEle(el, vnode, oldVnode)
if (oldCh && ch && oldCh !== ch) {
updateChildren(el, oldCh, ch)
}else if (ch){
createEle(vnode) //create el's children dom
}else if (oldCh){
api.removeChildren(el)
}
}
}
updateEle
,更新孩子节点是diff算法中最核心的部分。
下图中,菱形表示Vnode对象,圆形表示真实dom元素。下图中可以看到,当新旧children数目相同的时候,只需要patch即可。
未完待续……
8个生命周期函数
Reference
http://hcysun.me/vue-design/zh/renderer-diff.html
网友评论