关于key
上一张讲了vue的patch过程 有一点讲的还是很含糊的 就是key相关的
提到key这概念 在vue1.0中它的前身好像是v-track 作用不用说都知道 是为了优化diff操作 那它到底是如何做到这一点的呢
我们先看看代码
1 | if (isUndef(oldKeyToIdx)) { oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx); } |
这段代码是updateChildren方法里的一个if-branch 上一章节有提到这部分 我就不多赘述了
这段代码是干嘛的呢 先是通过oldVnodeChildren计算出老的子节点对应的key 每次updateChildren只需要计算一次
1 | function createKeyToOldIdx (children, beginIdx, endIdx) { |
也就是说如果一个节点有key 就把这个key当做map里的key值 把这个节点所处的index 当做value
比如一群子节点A, B, C, D key分别是’A’, ‘B’, ‘C’, ‘D’
生成的oldKeyToIdx就是1
2
3
4
5
6{
A: 0,
B: 1,
C: 2,
D: 3,
}
这样就算这些子节点的顺序变了 但是key没变 很容易能找到它在oldVnodesChildren中对应的节点 所以这才作为性能优化的一种手段
那为什么不推荐使用数组下标作为作为key呢
我们看看用数组下标作为key的oldKeyToIdx1
2
3
4
5
6{
0: 0,
1: 1,
2: 2,
3: 3,
}
这样如果子节点顺序发生了变化 比如变成了BADC 此时B的key由1变成了0 实际上我们在oldVnodesChildren中找到的是A
这时候如果A和B经过sameVnode判断不是同一个节点 会调用createElm创建新节点 那我们岂不是得不偿失啦 这样的key就没有意义了