key 是为 Vue 中的虚拟 DOM 节点(vNode)标记唯⼀性的 id。
作用: 给虚拟dom添加标识, (优化复用对比策略, 优化渲染性能)
主要考察:
-
vue 的更新机制 (差异化更新) 对比新旧虚拟dom 进行更新视图
为什么对比虚拟dom, 而不对比真实的dom ? 真实的dom太复杂, 对比起来性能太差
-
虚拟dom: 使用 js 对象的方式, 模拟真实的 dom 结构
属性的量大大的减少了, 没有真实dom的那么多无效的属性, 对比起来性能高很多
-
diff 算法: 默认的对比(diff) 机制, 同层兄弟元素, 是按照下标进行对比的, 但是加了 key, 就相当于给虚拟dom加了个标识
对比策略, 就是对相同key的元素进行对比了, 在列表v-for中, key的使用尤为常见, 可以用于优化渲染性能
diff算法
diff 算法的基本策略 (对比新旧虚拟dom差异的一种算法):
-
由于dom结构是一个树形结构, 就算是对比新旧虚拟dom, 一样是在对比树形结构
而树形结构, 每往下都一层, 遍历成本就越高
-
为了避免一些无效的对比, diff算法, (tree diff) 优先比较树的根节点
如果根节点元素类型(组件), 是一致的, 才考虑复用元素内部的结构
如果根节点元素类型(组件), 不一致, 直接销毁, 重新构建新的结构
旧 <div> <span>我是内容</span> </div> 新 <li> <a href="#">我是内容</a> <span>我是内容</span> </li>大大的提升了对比的效率
-
同一根节点下, 同级兄弟元素, 默认的对比策略: 按照下标对比
旧 <div class="box"> <h1>大标题</h1> <p>内容</p> </div> 新 <div class="message"> <h1>测试标题</h1> <p>内容</p> </div> -
同一根节点下, 同级兄弟元素, 如果配置 key 属性, 那么对比的策略, 就不是按照下标, 而是按照key进行 一一对比
旧 <div class="box"> <h1 key="201">大标题</h1> <p key="202">内容</p> </div> 新 <div class="message"> <h1 key="200">大标题</h1> // 新结构 <p key="202">内容</p> // 对比出来, 原来结构有key="202", 进行对比, 完成了复用 </div>如果你希望一个结构, 并不进行复用, 就是希望某个组件某个结构, 能够重新构建, 可以设置一个不同的 key
key的常见应用场景
key 的常见应用场景 => v-for, v-for 遍历的列表中的项的顺序, 非常的容易改变
1 往后面加, 默认的对比策略, 按照下标, 没有任何问题
// 旧
<ul>
<li>张三</li>
<li>李四</li>
</ul>
// 新
<ul>
<li>张三</li>
<li>李四</li>
<li>王五</li>
</ul>
2 往前面加, 由于下标变了, 如果按照之前的下标对比, 元素是混乱的, 策略: 加上key
一旦加上了key, 就是按照 key 进行新旧dom的对比了
// 旧
<ul>
<li key="17">张三</li>
<li key="31">李四</li>
</ul>
// 新 [ { id: 17, name: '张三' }, ... ]
<ul>
<li key="52">王五</li>
<li key="17">张三</li>
<li key="31">李四</li>
</ul>
总结: key 就是给 虚拟dom 添加了一个 标识, 优化了对比策略!!!
\