网站首页 > 技术文章 正文
我们打开“src/compiler/create-compiler.js”文件,代码如下:
function patchVnode ( oldVnode,vnode, insertedVnodeQueue,ownerArray, index, removeOnly ) {
// 节点是否相同
if (oldVnode === vnode) {
return
}
if (isDef(vnode.elm) && isDef(ownerArray)) {
// 克隆节点
vnode = ownerArray[index] = cloneVNode(vnode)
}
// 真实节点
const elm = vnode.elm = oldVnode.elm
if (isTrue(oldVnode.isAsyncPlaceholder)) {
if (isDef(vnode.asyncFactory.resolved)) {
hydrate(oldVnode.elm, vnode, insertedVnodeQueue)
} else {
vnode.isAsyncPlaceholder = true
}
return
}
if (isTrue(vnode.isStatic) && isTrue(oldVnode.isStatic) && vnode.key === oldVnode.key && (isTrue(vnode.isCloned) || isTrue(vnode.isOnce))) {
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)
}
// 旧vnode
const oldCh = oldVnode.children
// 新vnode
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)) {
// 更新子集
if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)
} else if (isDef(ch)) {
if (process.env.NODE_ENV !== 'production') {
// 验证key
checkDuplicateKeys(ch)
}
if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, '')
c
addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)
} else if (isDef(oldCh)) {
removeVnodes(oldCh, 0, oldCh.length - 1)
} else if (isDef(oldVnode.text)) {
nodeOps.setTextContent(elm, '')
}
} else if (oldVnode.text !== vnode.text) {
nodeOps.setTextContent(elm, vnode.text)
}
if (isDef(data)) {
if (isDef(i = data.hook) && isDef(i = i.postpatch)) i(oldVnode, vnode)
}
}
下面我还来拆分一下该代码进行分析。
if (oldVnode === vnode) {
return
}
首先可以看到这里是进行了一个简单是对比,oldVnode(旧) 等于 vnode 的话,那就直接返回了。
if (isDef(vnode.elm) && isDef(ownerArray)) {
// clone reused vnode
vnode = ownerArray[index] = cloneVNode(vnode)
}
vnode.elm属性存在,说明该节点已被渲染过,ownerArray存在于子元素更新的时候。
如果两者都存在的话,那就调用 “cloneVNode” 函数,复制一个节点出来。
if (isTrue(vnode.isStatic) &&
isTrue(oldVnode.isStatic) &&
vnode.key === oldVnode.key &&
(isTrue(vnode.isCloned) || isTrue(vnode.isOnce))
) {
vnode.componentInstance = oldVnode.componentInstance
return
}
可以看到该语句赋值了 “componentInstance” 属性之后就直接返回了。
需满足以下条件:
1、vnode必须是 isStatic (静态节点)
2、oldVnode必须是 isStatic (静态节点)
3、vnode和oldVnode 的key值必须相等
4、vnode是克隆的vnode节点或者是一次性节点(isOnce存在)
let i
const data = vnode.data
if (isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)) {
i(oldVnode, vnode)
}
这里主要是看是否存在“hook” 属性。
组件才会存在hook属性,有 init、prepatch、insert、destroy四个hook(钩子属性)
init 初始化组件
prepatch 更新组件
insert 插入到DOM原生中
destroy 销毁组件
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)
}
这里主要是执行更新操作,isPatchable 函数用于验证vnode是否存在 tag属性。
注释节点和纯文本节点不存在tag属性
update为数组,主要更新如下内容:
1、updateAttrs // 更新attr属性
2、updateClass // 更新class属性
3、updateDOMListeners // 更新事件
4、updateDOMProps // 更新props
5、updateStyle // 更新style
6、update // 更新引用
7、updateDrectives // 更新指令
// text属性不存在
if (isUndef(vnode.text)) {
if (isDef(oldCh) && isDef(ch)) {
// 更新子集vnode
if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)
} else if (isDef(ch)) {
if (process.env.NODE_ENV !== 'production') {
// 验证重复的key
checkDuplicateKeys(ch)
}
// 设置真实节点是文本值
if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, '')
// 添加新的vnode节点
addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)
} else if (isDef(oldCh)) {
// 移除vnode节点
removeVnodes(oldCh, 0, oldCh.length - 1)
} else if (isDef(oldVnode.text)) {
// 设置真实节点是文本值
nodeOps.setTextContent(elm, '')
}
} else if (oldVnode.text !== vnode.text) {
// 设置真实节点是文本值
nodeOps.setTextContent(elm, vnode.text)
}
以上代码最陌生的应该是 nodeOps 对象了,我们来看看该对象具有哪些功能:
1、createElement // 创建元素
2、createElementNS // 创建指定命名空间元素
3、createTextNode // c文本元素
4、createComment // // 创建注释元素
5、insertBefore // 插入元素之前
6、removeChild // 移除子节点
7、appendChild // 添加子节点
8、parentNode // 父级元素
9、nextSibling // 下一个兄弟元素
10、tagName // 标签名称
11、setTextContent // 设置文本内容
12、setStyleScope // 设置内联样式
猜你喜欢
- 2024-10-25 《王牌部队》高粱拿了“喜剧人”剧本,笑点泪点都被他承包了
- 2024-10-25 纯爱小说推荐|生活所迫,我只能把你的后宫变成我的兄弟了
- 2024-10-25 占星秒懂|宫位的形成与解析(下) 宫位意思
- 2024-10-25 农村兄弟建双拼更有气势还省钱,2020年超受欢迎的双拼户型分享
- 2024-10-25 我爸说,“你没有结婚,我在村子里比做贼还丢人!”
- 2024-10-25 「漫步计算机系统」之数据结构与算法(18):红黑树结点的删除
- 2024-10-25 IT兄弟连 HTML5教程 CSS3揭秘 CSS3概述
- 2024-10-25 通过css类/选择器选取元素 文档结构和遍历 元素树的文档
- 2024-10-25 琅琊榜:兄弟之情,远比男女之情更加动人
- 2024-10-25 参加兄弟婚礼祝福语 参加兄弟婚礼祝福语简短
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)