不传递key,就是单纯在 for 循环中根据索引来确定元素,只要当前索引下,新旧子节点的类型不一样,就不会复用该旧元素元素,而且先卸载 旧节点,再挂载新节点,造成性能浪费
const oldNode = [
{
type: 'p',
},
{
type: 'span',
},
]
const newNode = [
{
type: 'span',
}
{
type: 'p'
}
]
/**
* 一共需要4次操作才能完成Dom的更新
* 1. newVnode[0] oldNode[0] 直接patch(oldNode[0],newNode[0]),由于类型不一样,patch函数先把旧的 p节点删除,然后再次挂载 span节点
* 2. 同上操作
*/
代码解析
function patchChildren(n1,n2,container) {
if (typeof n2.children === 'string') {
// ...
} else if (Array.isArray(n2.children)) {
if (Array.isArray(n1.children)) {
for (let i = 0; i < n2.children.length; i ++) {
const newNode = n2.children[i]
const oldNode = n1.children[i]
/**
1. 旧节点中拿到了 type: p 类型的节点,新节点中拿到了 type: span的节点,直接调用 patch函数,patch函数处理时 n1.type(旧节点) !== n2.type(新节点) ,直接卸载了旧节点
2. 同上处理 type: span 和 type:p 类型的节点
* oldNode.type !== newNode.type 类型不一样,oldNode直接被卸载,然后挂载 newNode
*/
patch(oldNode,newNode,container)
}
}
}
}
function patch(n1,n2,container) {
if (!n1) {
mountElement(n2,container)
} else {
if(n1.type !== n2.type) {
// 都是走到了这里,直接把 旧节点卸载了
unmount(n1)
n1 = null
}
const {type} = n2
if (typeof n2 === 'string'){
if (!n1){
// 挂载 n2
mountElement(n2)
}
}
}
}