<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> <style> th,td{border: 1px solid black;} </style> </head> <body> <div id="app"> <h1>{{msg}}</h1> <table> <tr> <th>序号</th> <th>英雄</th> <th>能量值</th> <th>选择</th> </tr> <!-- VUE框架是采用了虚拟dom和diff算法来提高执行效率的 --> <!-- 虚拟dom是在内存中的dom对象 --> <!-- diff算法,可以快速比较两个对象的不同之处 --> <!-- 当我们没有设置key的时候,默认的key就是我们的index作为key的 --> <!-- v-for所在的标签中有一个很重要的属性key,这个key是这个dom元素的身份证号或者说唯一标识 --> <!-- 当我们没有设置key的时候默认为index作为key的标识 --> <!-- 内存中的虚拟dom生成的每一个tr上都会标识有一个唯一的key做区分 --> <!-- 类似于我们实体dom树上的id --> <!-- 当我们的diff算法比对时,发现没有变化,不会重新渲染,而是直接复用 --> <!-- 甚至连子元素都可以复用比较,不需要创建 --> <!-- 新的虚拟dom实际是在内存中的,他和老的已经渲染出来的实际dom进行比对 --> <!-- 比对不一样才修改,一样部分直接原地使用即可 --> <tr v-for="(hero,index) in heros" :key="hero.id"> <td>{{index}}</td> <td>{{hero.name}}</td> <td>{{hero.power}}</td> <td><input type="checkbox"/></td> </tr> </table> <button @click="addHero()">按一下</button> <!-- 采用index作为key存在什么问题? --> <!-- 第一个问题,效率低 --> <!-- 尽管真实dom上我们已经按下或选中了这个复选框了 --> <!-- 但是在内存中的虚拟dom不知道,所以他们比对以后,觉得没问题就会带着这个错乱的往下走 --> <!-- 就会导致这个被选中的走下去 --> <!-- 主要是针对非末尾元素的问题 --> <!-- push压入到末尾的元素不会导致这个问题,只有unshift到最前面的元素会产生这个问题 --> <!-- 不要使用默认的index就可以解决这个问题了 --> </div> <script> const vm = new Vue({ el : "#app", data : { msg : "Hello", heros : [ {id:"101",name:"Jerry",power:10000}, {id:"102",name:"Tom",power:9000}, {id:"103",name:"Jack",power:8000}, {id:"104",name:"Rose",power:6000} ] }, methods : { addHero() { this.heros.unshift({id:"1000",name:"Top",power:4000}); } } }); </script> </body> </html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/vue.js"></script>
<style>
th,td{border: 1px solid black;}
</style>
</head>
<body>
<div id="app">
<h1>{{msg}}</h1>
<table>
<tr>
<th>序号</th>
<th>英雄</th>
<th>能量值</th>
<th>选择</th>
</tr>
<!-- VUE框架是采用了虚拟dom和diff算法来提高执行效率的 -->
<!-- 虚拟dom是在内存中的dom对象 -->
<!-- diff算法,可以快速比较两个对象的不同之处 -->
<!-- 当我们没有设置key的时候,默认的key就是我们的index作为key的 -->
<!-- v-for所在的标签中有一个很重要的属性key,这个key是这个dom元素的身份证号或者说唯一标识 -->
<!-- 当我们没有设置key的时候默认为index作为key的标识 -->
<!-- 内存中的虚拟dom生成的每一个tr上都会标识有一个唯一的key做区分 -->
<!-- 类似于我们实体dom树上的id -->
<!-- 当我们的diff算法比对时,发现没有变化,不会重新渲染,而是直接复用 -->
<!-- 甚至连子元素都可以复用比较,不需要创建 -->
<!-- 新的虚拟dom实际是在内存中的,他和老的已经渲染出来的实际dom进行比对 -->
<!-- 比对不一样才修改,一样部分直接原地使用即可 -->
<tr v-for="(hero,index) in heros" :key="hero.id">
<td>{{index}}</td>
<td>{{hero.name}}</td>
<td>{{hero.power}}</td>
<td><input type="checkbox"/></td>
</tr>
</table>
<button @click="addHero()">按一下</button>
<!-- 采用index作为key存在什么问题? -->
<!-- 第一个问题,效率低 -->
<!-- 尽管真实dom上我们已经按下或选中了这个复选框了 -->
<!-- 但是在内存中的虚拟dom不知道,所以他们比对以后,觉得没问题就会带着这个错乱的往下走 -->
<!-- 就会导致这个被选中的走下去 -->
<!-- 主要是针对非末尾元素的问题 -->
<!-- push压入到末尾的元素不会导致这个问题,只有unshift到最前面的元素会产生这个问题 -->
<!-- 不要使用默认的index就可以解决这个问题了 -->
</div>
<script>
const vm = new Vue({
el : "#app",
data : {
msg : "Hello",
heros : [
{id:"101",name:"Jerry",power:10000},
{id:"102",name:"Tom",power:9000},
{id:"103",name:"Jack",power:8000},
{id:"104",name:"Rose",power:6000}
]
},
methods : {
addHero()
{
this.heros.unshift({id:"1000",name:"Top",power:4000});
}
}
});
</script>
</body>
</html>
VUE框架在虚拟dom和diff算法下key的作用及原理剖析------VUE框架
于 2023-11-30 10:41:49 首次发布