DOM和虚拟DOM
DOM是由HTML解析器 由上到下,从左到右读取标签,把他们分解成节点,构建DOM树;
虚拟DOM:当页面展示的内容更新的时候,如果我们通过操作真实的DOM,DOM操作的执行速度和js的速度有差异,js远比DOM操作的执行快,并且DOM操作也会引起浏览器的回流和重绘;
虚拟DOM就是为了解决浏览器性能问题而出现,用js对象模拟DOM节点,把一些DOM操作保存到一个js对象,在改变DOM之前,会先比较虚拟DOM的数据,不一致,才会将改变应用到真实DOM上。
简单来说:我们只需要操作虚拟DOM,然后再用虚拟DOM跟真实DOM比较,不一样的地方才去更新它(真实DOM);减少了真实DOM的操作次数
回流:当页面中的元素的大小或是位置等发生改变,浏览器会根据改变对页面的结构重新计算
重绘:当页面中元素的背景,颜色改变引发浏览器对元素重新描绘。
康康源码
function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) {
/*新旧节点相同则直接返回*/
if (oldVnode === vnode) {
return
}
if (isTrue(vnode.isStatic) &&
isTrue(oldVnode.isStatic) &&
vnode.key === oldVnode.key &&
(isTrue(vnode.isCloned) || isTrue(vnode.isOnce))) {
vnode.elm = oldVnode.elm
vnode.componentInstance = oldVnode.componentInstance
return
}
let i
const data = vnode.data
if (isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)) {
i(oldVnode, vnode)
}
const elm = vnode.elm = oldVnode.elm
const oldCh = oldVnode.children
const ch = vnode.children
if (isDef(data) && isPatchable(vnode)) {
for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode)
if (isDef(i = data.hook) && isDef(i = i.update)) i(oldVnode, vnode)
}
if (isUndef(vnode.text)) {
//判断是否都有子节点
if (isDef(oldCh) && isDef(ch)) {
/*新老节点均有children子节点,则对子节点进行diff操作,调用updateChildren*/
if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)
} else if (isDef(ch)) {
/*如果老节点没有子节点而新节点存在子节点,先清空elm的文本内容,然后为当前节点加入子节点*/
if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, '')
addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)
} else if (isDef(oldCh)) {
/*新节点没有子节点而老节点有子节点的时候,则移除所有ele的子节点*/
removeVnodes(elm, oldCh, 0, oldCh.length - 1)
} else if (isDef(oldVnode.text)) {
/*新老节点都无子节点的时候,只是文本的替换,因为这个逻辑中新节点text没有,所以直接去除ele的文本*/
nodeOps.setTextContent(elm, '')
}
} else if (oldVnode.text !== vnode.text) {
/*当新老节点text不一样时,直接替换这段文本*/
nodeOps.setTextContent(elm, vnode.text)
}
if (isDef(data)) {
if (isDef(i = data.hook) && isDef(i = i.postpatch)) i(oldVnode, vnode)
}
}
通过源码可以看到是先进行有无子节点判断,然后再进行同级比较;就是我们讲的先深度优先,再广度优先 END
上个小测试
<transition name="fade">
<p v-if="show">我第一</p>
<p v-else>我第二</p>
</transition>
transition是给切换添加过渡效果的,当变换变量show时,这个切换会不会出现淡入淡出过渡效果呢?为什么?