在Vue中使用v-for渲染列表时,默认使用就地更新策略。该策略默认是基于索引的,规定在列表绑定的数据元素顺序变化时,不会重新创建整个列表,而只是更新对应DOM元素上的数据。以下代码实现了一个TODO列表的勾选、添加和删除功能:

<!DOCTYPE html>
<html> <head>
<title>In-Place Update Example</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head> <body>
<div id="app">
<ul>
<li v-for="(todo, index) in todos" :key="index">
<input type="checkbox" v-model="todo.completed">
{{ todo.text }}
<button @click="removeTodo(index)">Remove</button>
</li>
</ul>
<button @click="addTodo">Add Todo</button>
</div> <script>
const app = new Vue({
el: '#app',
data: {
todos: [
{ text: 'Learn Vue.js', completed: false },
{ text: 'Build an app', completed: true },
{ text: 'Deploy to production', completed: false }
]
},
methods: {
removeTodo(index) {
this.todos.splice(index, 1);
},
addTodo() {
this.todos.push({ text: 'New Todo', completed: false });
}
}
});
</script>
</body> </html>

该策略模式是高效的,避免了大量的DOM重排重绘。

然而,该策略基于一个前提:列表项内部的内容不依赖于子组件的状态或临时的DOM状态。如违背该前提,就可能导致意外,因为Vue不会重新创建子组件或恢复临时DOM状态。

下面代码实现了v-for列表项内容依赖于子组件的状态而导致意外的情况:

<!DOCTYPE html>
<html> <head>
<title>In-Place Update with Child Component</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head> <body>
<div id="app">
<!-- 使用 v-for 渲染子组件列表 -->
<child-component v-for="(item, index) in itemList" :key="index"
@remove="removeItem(index)"></child-component>
</div> <script>
Vue.component('child-component', {
template: `
<div>
<!-- 子组件的内容和状态 -->
<button @click="increment">{{ count }}</button>
<!-- 删除 -->
<button @click="$emit('remove')">删除</button>
</div>
`,
methods: {
increment() {
this.count++;
}
},
data(){
return{
count:0
}
}
}); const app = new Vue({
el: '#app',
data: {
itemList: new Array(5).fill(null)
},
methods: {
removeItem(index) {
this.itemList.splice(index, 1);
}
}
});
</script>
</body> </html>

我们先点击某项计数器,再删除该项:

为了解决该问题,我们为每一项绑定一个唯一的key属性:

<!DOCTYPE html>
<html> <head>
<title>In-Place Update with Child Component</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head> <body>
<div id="app">
<!-- 使用 v-for 渲染子组件列表 -->
<child-component v-for="(item, index) in itemList" :key="item.id"
@remove="removeItem(index)"></child-component>
</div> <script>
Vue.component('child-component', {
template: `
<div>
<!-- 子组件的内容和状态 -->
<button @click="increment">{{ count }}</button>
<!-- 删除 -->
<button @click="$emit('remove')">删除</button>
</div>
`,
methods: {
increment() {
this.count++;
}
},
data(){
return{
count:0
}
}
}); const app = new Vue({
el: '#app',
data: {
// 为每一项添加一个id
itemList: [
{ id: 0 },
{ id: 1 },
{ id: 2 }
]
},
methods: {
removeItem(index) {
this.itemList.splice(index, 1);
}
}
});
</script>
</body> </html>

效果如下:

那么就有疑问了:为什么前面代码中的key属性绑定了index没有用呢,index难道不是唯一的吗?很简单,这是由于我们删除的是数据项,而不是数组索引,使用id就不会有这个问题,删除一项连带着删除了该唯一id。

关于Vue的就地更新策略的解析的更多相关文章

  1. Unity手游之路<十三>手游代码更新策略探讨

    http://blog.csdn.net/janeky/article/details/25923151 这几个月公司项目非常忙,加上家里事情也多,所以blog更新一直搁置了.最近在项目开发上线过程中 ...

  2. Unity手游之路手游代码更新策略探讨

    版权声明: https://blog.csdn.net/janeky/article/details/25923151 这几个月公司项目非常忙.加上家里事情也多,所以blog更新一直搁置了. 近期在项 ...

  3. vue的就地复用--- v-for与:key

    v-for遵循的是vue的就地复用原则.文本与数据是绑定的,所以当文本被重新渲染的时候,列表也会被重新渲染. 就地复用只适用于不依赖子组件状态或临时DOM状态的列表渲染输出.[比如表单输入值的列表渲染 ...

  4. Unity手游之路<十二>手游资源热更新策略探讨

    http://blog.csdn.net/janeky/article/details/17666409 上一次我们学习了如何将资源进行打包.这次就可以用上场了,我们来探讨一下手游资源的增量更新策略. ...

  5. 分布式系统中一些主要的副本更新策略——Dynamo/Cassandra/Riak同时采取了主从式更新的同步+异步类型,以及任意节点更新的策略。

    分布式系统中一些主要的副本更新策略. 1.同时更新 类型A:没有任何协议,可能出现多个节点执行顺序交叉导致数据不一致情况. 类型B:通过一致性协议唯一确定不同更新操作的执行顺序,从而保证数据一致性 2 ...

  6. [unity3d]手游资源热更新策略探讨

    原地址:http://blog.csdn.net/dingxiaowei2013/article/details/20079683 我们学习了如何将资源进行打包.这次就可以用上场了,我们来探讨一下手游 ...

  7. 利用Dnspod api批量更新添加DNS解析【python脚本】 - 推酷

    利用Dnspod api批量更新添加DNS解析[python脚本] - 推酷 undefined

  8. odi增量更新策略

    增量更新策略:通过一个“update key”比较流数据记录与目标表中的记录比较进行数据整合.具有相同“update key”的记录当相关联列不同时将被更新:在目标表中不存在的记录将被插入.这种方式用 ...

  9. vue加载优化策略

    vue.js是一个比较流行的前端框架,与react.js.angular.js相比来说,vue.js入手曲线更加流畅,不管掌握多少都可以快速上手.但是单页面应用也都有其弊病,有时候首屏加载慢的让人捏舌 ...

  10. [转]Unity手游之路<十二>手游资源热更新策略探讨

    最近梳理了下游戏流程.恩,本来想写下,但是,还是看前辈的吧 版权声明: https://blog.csdn.net/janeky/article/details/17666409 上一次我们学习了如何 ...

随机推荐

  1. 2021-02-18:给定一个字符串str,给定一个字符串类型的数组arr,出现的字符都是小写英文。arr每一个字符串,代表一张贴纸,你可以把单个字符剪开使用,目的是拼出str来。返回需要至少多少张贴纸可以完成这个任务。例子:str= "babac",arr = {"ba","c","abcd"}。a + ba + c 3 abcd + abcd 2 abcd+ba 2。所以返回2。

    2021-02-18:给定一个字符串str,给定一个字符串类型的数组arr,出现的字符都是小写英文.arr每一个字符串,代表一张贴纸,你可以把单个字符剪开使用,目的是拼出str来.返回需要至少多少张贴 ...

  2. 2021-11-01:寻找重复数。给定一个包含 n + 1 个整数的数组 nums ,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设 nums 只有 一个重复的整数

    2021-11-01:寻找重复数.给定一个包含 n + 1 个整数的数组 nums ,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设 nums 只有 一个重复的整数 ...

  3. Netty(1)——NIO基础

    本篇主要介绍Java NIO的基本原理和主要组件 Netty是由JBOSS提供的Java开源网络应用程序框架,其底层是基于Java提供的NIO能力实现的.因此为了掌握Netty的底层原理,需要首先了解 ...

  4. drf序列化器之反序列化的数据验证

    模型层 from django.db import models # Create your models here. class Manufacturer(models.Model): ## 厂商 ...

  5. 百度飞桨(PaddlePaddle) - PP-OCRv3 文字检测识别系统 Paddle Inference 模型推理

    Paddle Inference 模型推理流程 分别介绍文字检测.方向分类器和文字识别3个模型,基于Paddle Inference的推理过程. Paddle Inference 的 Python 离 ...

  6. ImageMagick 图像处理学习笔记

    Use ImageMagick to create, edit, compose, or convert bitmap images. It can read and write images in ...

  7. Win32 GUI 汇编

    获取句柄 API函数 GetModuleHandle 取模块句柄,lpModuleName 是一个指向模块名称字符串的指针,使用 NULL 获取当前程序句柄. invoke GetModuleHand ...

  8. Android Studio 引入kotlin 协程

    首先保证创建了kotlin项目,然后,两个步骤: 1. 加入dependency,在 build.gradle(:app)中,加入 implementation 'org.jetbrains.kotl ...

  9. Java 集合框架体系简介

    为什么要使用集合 存储多个数据可以使用数组,但由于数组在内存中是连续存储的,所以会有一些限制.比如数组在创建时就要指定长度,即可以容纳的元素个数,且指定后无法更改:数组在创建时需要指定元素的类型,并且 ...

  10. 使用GoEasy快速实现Android原生app中的websocket消息推送

    摘要: GoEasy带来了一项令开发者振奋的消息:全面支持Android原生平台!现在,您可以在Android应用中使用最酷炫的实时通信功能,借助GoEasy轻松实现消息的发送和接收.本文将带您领略G ...