>  기사  >  웹 프론트엔드  >  Vue에서 키의 역할에 대한 자세한 코드 설명 예시

Vue에서 키의 역할에 대한 자세한 코드 설명 예시

coldplay.xixi
coldplay.xixi앞으로
2020-07-11 17:43:282308검색

Vue에서 키의 역할에 대한 자세한 코드 설명 예시

Vue

의 특수 속성은 주로 Vue 가상화에 사용됩니다. DOM 알고리즘은 이전 노드를 비교할 때 VNodes를 식별합니다. 가 사용되지 않으면 Vue는 동적 요소를 최소화하고 동일한 유형의 요소를 최대한 수정하고 재사용하려고 시도하는 알고리즘을 대신 사용합니다. >key, 변경에 따라 요소 순서를 재정렬하고 가 존재하지 않는 요소를 제거합니다. 또한 동일한 상위 요소가 있는 하위 요소에는 고유한 가 있어야 합니다. 가 중복되면 렌더링 오류가 발생합니다. 的特殊attribute主要用在Vue的虚拟DOM算法,在新旧Nodes对比时辨识VNodes。如果不使用Vue会使用一种最大限度减少动态元素并且尽可能的尝试就地修改、复用相同类型元素的算法,而使用时,它会基于的变化重新排列元素顺序,并且会移除不存在的元素。此外有相同父元素的子元素必须有独特的,重复的会造成渲染错误。

相关学习推荐:javascript视频教程

描述

首先是官方文档的描述,当Vue正在更新使用v-for渲染的元素列表时,它默认使用就地更新的策略,如果数据项的顺序被改变,Vue将不会移动DOM元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时DOM状态的列表渲染输出,例如表单输入值。为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 ,建议尽可能在使用v-for时提供,除非遍历输出的DOM内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

简单来说,当在列表循环中使用时,需要使用来给每个节点做一个唯一标识,diff算法就可以正确的识别此节点,找到正确的位置直接操作节点,尽可能地进行重用元素,的作用主要是为了高效的更新虚拟DOM。此外,使用index作为是并不推荐的做法,其只能保证Vue在数据变化时强制更新组件,以避免原地复用带来的副作用,但不能保证最大限度的元素重用,且使用index作为在数据更新方面和不使用的效果基本相同。

示例

首先定义一个Vue实例,渲染四个列表,分别为简单列表与复杂列表,以及其分别携带与不携带时对比其更新渲染时的速度,本次测试使用的是Chrome 81.0,每次在Console执行代码时首先会进行刷新重新加载界面,避免浏览器以及Vue自身优化带来的影响。

<!DOCTYPE html>
<html>
<head>
 <title>Vue</title>
</head>
<body>
 <p id="app">
 <ul>
 <li v-for="item in simpleListWithoutKey" >{{item}}</li>
 </ul>

 <ul>
 <li v-for="item in simpleListWithKey" :key="item" >{{item}}</li>
 </ul>

 <ul>
 <li v-for="item in complexListWithoutKey">
 <span v-for="value in item.list" v-if="value > 5">{{value}}</span>
 </li>
 </ul>

 <ul>
 <li v-for="item in complexListWithKey" :key="item.id">
 <span v-for="value in item.list" :key="value" v-if="value > 5">{{value}}</span>
 </li>
 </ul>

 </p>
</body>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<script type="text/javascript">
 var vm = new Vue({
 el: &#39;#app&#39;,
 data: {
 simpleListWithoutKey: [1, 2, 3, 4, 5, 6],
 simpleListWithKey: [1, 2, 3, 4, 5, 6],
 complexListWithoutKey:[
 {id: 1, list: [1, 2, 3]},
 {id: 2, list: [4, 5, 6]},
 {id: 3, list: [7, 8, 9]}
 ],
 complexListWithKey:[
 {id: 1, list: [1, 2, 3]},
 {id: 2, list: [4, 5, 6]},
 {id: 3, list: [7, 8, 9]}
 ],
 }
 })
</script>
</html>

简单列表

在简单列表的情况下,不使用可能会比使用的情况下在更新时的渲染速度更快,这也就是官方文档中提到的,除非遍历输出的DOM内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。在下面的例子中可以看到没有的情况下列表更新时渲染速度会快,当不存在的情况下,这个列表直接进行原地复用,原有的节点的位置不变,原地复用元素,将内容更新为5678910,并添加了1112两个节点,而存在的情况下,原有的1234节点被删除,56节点保留,添加了789101112六个节点,由于在DOM的增删操作上比较耗时,所以表现为不带的情况下速度更快一些。

// 没有key的情况下
console.time();
vm.simpleListWithoutKey = [5, 6, 7, 8, 9, 10, 11, 12];
vm.$nextTick(() => console.timeEnd());
// default: 2.193056640625ms
// 存在key的情况下
console.time();
vm.simpleListWithKey = [5, 6, 7, 8, 9, 10, 11, 12];
vm.$nextTick(() => console.timeEnd());
// default: 3.2138671875ms

原地复用可能会带来一些副作用,文档中提到原地复用这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时DOM

관련 학습 권장사항: 자바스크립트 동영상 튜토리얼🎜
🎜🎜🎜Description🎜🎜🎜🎜첫 번째는 공식 문서의 설명으로, Vuev-for 내부 업데이트 전략, 데이터 항목의 순서가 변경되면 <code>Vue는 데이터 항목의 순서와 일치하도록 DOM 요소를 이동하지 않고 각 요소를 업데이트합니다. in-place 요소를 사용하고 각 인덱스 위치에서 올바르게 렌더링되는지 확인하세요. 이 기본 모드는 효율적이지만 하위 구성 요소 상태나 임시 DOM 상태(예: 양식 입력 값)에 의존하지 않는 목록 렌더링 출력에만 적합합니다. 각 노드의 ID를 추적하여 기존 요소를 재사용하고 재정렬할 수 있도록 Vue에 힌트를 제공하려면 고유한 을 제공해야 합니다. 출력 DOM을 순회하는 것이 매우 간단하지 않은 한, 가능하면 v-for를 사용할 때 을 제공하는 것이 좋습니다. 콘텐츠를 사용하거나 의도적으로 기본 동작을 사용하여 성능을 향상시킵니다. 🎜🎜간단히 말하면, 목록 루프에서 를 사용할 때 각 노드를 고유하게 식별하려면 를 사용해야 합니다. diff 알고리즘은 올바르게 이 노드를 식별하고 올바른 위치를 찾아 노드를 직접 작동하고, 요소를 최대한 재사용하는 것이 의 주요 역할은 가상 DOM을 효율적으로 업데이트하는 것입니다. 또한 index로 사용하는 것은 권장되지 않습니다. 이는 데이터가 변경될 때 Vue가 구성 요소를 강제로 업데이트하도록 보장할 뿐입니다. 로컬 재사용으로 인해 원래 부작용이 발생했지만 최대 요소 재사용을 보장할 수 없으며 데이터 업데이트에서 index로 사용하고 를 사용하지 마세요. 효과는 기본적으로 동일합니다. 🎜🎜🎜🎜Example🎜🎜🎜🎜먼저 Vue 인스턴스를 정의하고 4개의 목록, 즉 단순 목록과 복합 목록, 를 전달하는 목록과 를 사용할 때의 업데이트 속도와 렌더링 속도를 비교해보세요. 에서 코드가 실행될 때마다 먼저 실행되는 <code>Chrome 81.0을 사용합니다. 콘솔 브라우저와 Vue 자체 최적화의 영향을 피하기 위해 인터페이스를 새로 고치고 다시 로드합니다. 🎜
<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width">
 <title>就地复用</title>
</head>
<body>

 <p id="app">
 <h3>采用就地复用策略(vuejs默认情况)</h3>
 <p v-for=&#39;(p, i) in persons&#39;>
 <span>{{p.name}}<span> 
 <input type="text"/> 
 <button @click=&#39;down(i)&#39; v-if=&#39;i != persons.length - 1&#39;>下移</button>
 </p> 

 <h3>不采用就地复用策略(设置key)</h3>
 <p v-for=&#39;(p, i) in persons&#39; :key=&#39;p.id&#39;>
 <span>{{p.name}}<span> 
 <input type="text"/> 
 <button @click=&#39;down(i)&#39; v-if=&#39;i != persons.length - 1&#39;>下移</button>
 </p>

 </p>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
 <script>
 new Vue({
 el: &#39;#app&#39;,
 data: {
 persons: [
 { id: 1, name: &#39;A&#39; },
 { id: 2, name: &#39;B&#39; },
 { id: 3, name: &#39;C&#39; }
 ]
 },
 mounted: function(){
 // 此DOM操作将两个A的颜色设置为红色 主要是为了演示原地复用
 document.querySelectorAll("h3 + p > span:first-child").forEach( v => v.style.color="red");
 },
 methods: {
 down: function(i) {
 if (i == this.persons.length - 1) return;
 var listClone = this.persons.slice();
 var one = listClone[i];
 listClone[i] = listClone[i + 1];
 listClone[i + 1] = one;
 this.persons = listClone;
 }
 }
 });
 </script>
</body>
</html>
<!-- 源于 https://www.zhihu.com/question/61078310 @霸都丶傲天 有修改-->
🎜🎜🎜간단한 목록🎜🎜🎜🎜간단한 목록의 경우 를 사용하는 것보다 를 사용하지 않는 것이 업데이트 시 더 빠르게 렌더링될 수 있습니다. Fast, 이것이 바로 출력 DOM 콘텐츠를 순회하는 것이 매우 간단하거나 의도적으로 기본 동작에 의존하여 성능 향상을 얻는 것이 아니라면 공식 문서에 언급되어 있습니다. 다음 예에서는 없이 목록을 업데이트하면 렌더링 속도가 더 빨라지는 것을 확인할 수 있습니다. 가 없으면 목록이 바로 그 자리에 복원됩니다. 를 사용하면 원래 노드의 위치는 변경되지 않고 요소는 제자리에 재사용되며 콘텐츠는 5, 6, 7로 업데이트됩니다. >, 8, 9, 10, 두 개의 노드 1112는 추가되었으며, 가 존재할 경우 원래 1, 2, 3, 4노드가 삭제되고, 5, 6 노드가 유지되고, 7, 8, 9, <code>10, 11, 12 6개 노드를 추가했습니다. DOM의 추가 및 삭제 작업은 다음과 같습니다. 상대적으로 시간이 많이 걸리므로 가 없으면 더 빠릅니다. 🎜
console.time();
vm.complexListWithoutKey = [
 {id: 3, list: [7, 8, 9]},
 {id: 2, list: [4, 5, 6]},
 {id: 1, list: [1, 2, 3]},
 ];
vm.$nextTick(() => console.timeEnd());
vm.$nextTick(() => console.timeEnd());
// default: 4.100244140625ms
console.time();
vm.complexListWithKey = [
 {id: 3, list: [7, 8, 9]},
 {id: 2, list: [4, 5, 6]},
 {id: 1, list: [1, 2, 3]},
 ];
vm.$nextTick(() => console.timeEnd());
// default: 3.016064453125ms
🎜내부 재사용은 일부 부작용을 가져올 수 있습니다. 문서에서는 내부 재사용의 기본 모드가 효율적이라고 언급하지만 하위 구성 요소 상태 또는 임시 DOM에 의존하지 않는 상황에만 적합합니다. 상태. 양식 입력 값과 같은 렌더링된 출력 목록입니다. 🎜

在不设置的情况下,元素中没有与数据data绑定的部分,Vue会默认使用已经渲染的DOM,而绑定了数据data的部分会进行跟随数据渲染,假如操作了元素位置,则元素中未绑定data的部分会停留在原地,而绑定了data的部分会跟随操作进行移动,在下面的例子中首先需要将两个A之后的输入框添加数据信息,这样就制作了一个临时状态,如果此时点击下移按钮,那么不使用的组中的输入框将不会跟随下移,且B到了顶端并成为了红色,而使用的组中会将输入框进行下移,且A依旧是红色跟随下移。

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width">
 <title>就地复用</title>
</head>
<body>

 <p id="app">
 <h3>采用就地复用策略(vuejs默认情况)</h3>
 <p v-for=&#39;(p, i) in persons&#39;>
 <span>{{p.name}}<span> 
 <input type="text"/> 
 <button @click=&#39;down(i)&#39; v-if=&#39;i != persons.length - 1&#39;>下移</button>
 </p> 

 <h3>不采用就地复用策略(设置key)</h3>
 <p v-for=&#39;(p, i) in persons&#39; :key=&#39;p.id&#39;>
 <span>{{p.name}}<span> 
 <input type="text"/> 
 <button @click=&#39;down(i)&#39; v-if=&#39;i != persons.length - 1&#39;>下移</button>
 </p>

 </p>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
 <script>
 new Vue({
 el: &#39;#app&#39;,
 data: {
 persons: [
 { id: 1, name: &#39;A&#39; },
 { id: 2, name: &#39;B&#39; },
 { id: 3, name: &#39;C&#39; }
 ]
 },
 mounted: function(){
 // 此DOM操作将两个A的颜色设置为红色 主要是为了演示原地复用
 document.querySelectorAll("h3 + p > span:first-child").forEach( v => v.style.color="red");
 },
 methods: {
 down: function(i) {
 if (i == this.persons.length - 1) return;
 var listClone = this.persons.slice();
 var one = listClone[i];
 listClone[i] = listClone[i + 1];
 listClone[i + 1] = one;
 this.persons = listClone;
 }
 }
 });
 </script>
</body>
</html>
<!-- 源于 https://www.zhihu.com/question/61078310 @霸都丶傲天 有修改-->

复杂列表

使用不仅能够避免上述的原地复用的副作用,且在一些操作上可能能够提高渲染的效率,主要体现在重新排序的情况,包括在中间插入和删除节点的操作,在下面的例子中没有的情况下重新排序会原地复用元素,

但是由于v-if绑定了data所以会一并进行操作,在这个DOM操作上比较消耗时间,而使用得情况则直接复用元素,v-if控制的元素在初次渲染就已经决定,在本例中没有对其进行更新,所以不涉及v-ifDOM操作,所以在效率上会高一些。

console.time();
vm.complexListWithoutKey = [
 {id: 3, list: [7, 8, 9]},
 {id: 2, list: [4, 5, 6]},
 {id: 1, list: [1, 2, 3]},
 ];
vm.$nextTick(() => console.timeEnd());
vm.$nextTick(() => console.timeEnd());
// default: 4.100244140625ms
console.time();
vm.complexListWithKey = [
 {id: 3, list: [7, 8, 9]},
 {id: 2, list: [4, 5, 6]},
 {id: 1, list: [1, 2, 3]},
 ];
vm.$nextTick(() => console.timeEnd());
// default: 3.016064453125ms

위 내용은 Vue에서 키의 역할에 대한 자세한 코드 설명 예시의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 jb51.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제