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

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>In-Place Update Example</title>
  5. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
  6. </head>
  7. <body>
  8. <div id="app">
  9. <ul>
  10. <li v-for="(todo, index) in todos" :key="index">
  11. <input type="checkbox" v-model="todo.completed">
  12. {{ todo.text }}
  13. <button @click="removeTodo(index)">Remove</button>
  14. </li>
  15. </ul>
  16. <button @click="addTodo">Add Todo</button>
  17. </div>
  18. <script>
  19. const app = new Vue({
  20. el: '#app',
  21. data: {
  22. todos: [
  23. { text: 'Learn Vue.js', completed: false },
  24. { text: 'Build an app', completed: true },
  25. { text: 'Deploy to production', completed: false }
  26. ]
  27. },
  28. methods: {
  29. removeTodo(index) {
  30. this.todos.splice(index, 1);
  31. },
  32. addTodo() {
  33. this.todos.push({ text: 'New Todo', completed: false });
  34. }
  35. }
  36. });
  37. </script>
  38. </body>
  39. </html>

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

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

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

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>In-Place Update with Child Component</title>
  5. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
  6. </head>
  7. <body>
  8. <div id="app">
  9. <!-- 使用 v-for 渲染子组件列表 -->
  10. <child-component v-for="(item, index) in itemList" :key="index"
  11. @remove="removeItem(index)"></child-component>
  12. </div>
  13. <script>
  14. Vue.component('child-component', {
  15. template: `
  16. <div>
  17. <!-- 子组件的内容和状态 -->
  18. <button @click="increment">{{ count }}</button>
  19. <!-- 删除 -->
  20. <button @click="$emit('remove')">删除</button>
  21. </div>
  22. `,
  23. methods: {
  24. increment() {
  25. this.count++;
  26. }
  27. },
  28. data(){
  29. return{
  30. count:0
  31. }
  32. }
  33. });
  34. const app = new Vue({
  35. el: '#app',
  36. data: {
  37. itemList: new Array(5).fill(null)
  38. },
  39. methods: {
  40. removeItem(index) {
  41. this.itemList.splice(index, 1);
  42. }
  43. }
  44. });
  45. </script>
  46. </body>
  47. </html>

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

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

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>In-Place Update with Child Component</title>
  5. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
  6. </head>
  7. <body>
  8. <div id="app">
  9. <!-- 使用 v-for 渲染子组件列表 -->
  10. <child-component v-for="(item, index) in itemList" :key="item.id"
  11. @remove="removeItem(index)"></child-component>
  12. </div>
  13. <script>
  14. Vue.component('child-component', {
  15. template: `
  16. <div>
  17. <!-- 子组件的内容和状态 -->
  18. <button @click="increment">{{ count }}</button>
  19. <!-- 删除 -->
  20. <button @click="$emit('remove')">删除</button>
  21. </div>
  22. `,
  23. methods: {
  24. increment() {
  25. this.count++;
  26. }
  27. },
  28. data(){
  29. return{
  30. count:0
  31. }
  32. }
  33. });
  34. const app = new Vue({
  35. el: '#app',
  36. data: {
  37. // 为每一项添加一个id
  38. itemList: [
  39. { id: 0 },
  40. { id: 1 },
  41. { id: 2 }
  42. ]
  43. },
  44. methods: {
  45. removeItem(index) {
  46. this.itemList.splice(index, 1);
  47. }
  48. }
  49. });
  50. </script>
  51. </body>
  52. </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. 2023-02-20:小A认为如果在数组中有一个数出现了至少k次, 且这个数是该数组的众数,即出现次数最多的数之一, 那么这个数组被该数所支配, 显然当k比较大的时候,有些数组不被任何数所支配。 现在

    2023-02-20:小A认为如果在数组中有一个数出现了至少k次, 且这个数是该数组的众数,即出现次数最多的数之一, 那么这个数组被该数所支配, 显然当k比较大的时候,有些数组不被任何数所支配. 现在 ...

  2. 2021-10-13:单词接龙。字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列:序列中第一个单词是 beginWord 。序列中最后

    2021-10-13:单词接龙.字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列:序列中第一个单词是 beginWord .序列中最后 ...

  3. DevEco Studio 3.1 Release | 动态共享包开发,编译更快,包更小

      原文:https://mp.weixin.qq.com/s/qPvHZNZuLccAsviBcXtPWw,点击链接查看更多技术内容. 动态共享包(HSP)开发是DevEco Studio 3.1  ...

  4. 去掉谷歌/新版Edge 浏览器的禁用扩展提示

    简介 你打开是谷歌/新版Edge浏览器的时候是不是总发现右上角有个提示?请禁用/停用以开发者模式运行的扩展程序?每次打开都有一个小框框,让人很烦? 接下来让我们使用 dll大法 来解决这个问题! 步骤 ...

  5. 【数据库】时区及JDBC的时区设置

    JDBC连接时有个TimeZone配置,这玩意到底有用吗?我是使用Postgresql和Mysql两个数据库验证的.结果如下: 数据库 部署方式 版本 JDBC连接TimeZone参数 JDBC连接s ...

  6. 计算机网络 ACL和ANT

    目录 一.ACL概况 二.ACL工作过程 三.ACL实验 四.ANT概况 五.ANT工作过程 六.ANT实验 一.ACL概况 概念:主要是对报文进行区分,路由器会对报文进行检查,查看是否符合通过标准或 ...

  7. 《Just For Fun》:学习即游戏

    <Just For Fun>:学习即游戏 最近读完了 Linus 的自传<Just For Fun>,一直想写点东西,但始终苦于工作繁忙,无暇思考该从何写起.技术上自然不用废话 ...

  8. 一定要看的前端codeReview规范指南

    一.前言 针对目录结构.CSS规范.JavaScript规范.Vue规范 可参照官方给出的 风格指南 这里主要总结业务开发中常遇到的代码问题和实践,帮助大家后续各自做好codeReview,一些你遇到 ...

  9. Lucene检索全流程学习笔记

    一 简介 写作目的 1 为什么学习Lucene lucene是基于倒排索引的检索工具库,倒排索引是典型的文本匹配,它能够精确匹配用户搜索的query,它的缺点是不擅长语义理解,而深度学习检索模型擅长的 ...

  10. Open AI ChatGPT Prompt 学习之基础篇

    碎碎念 2023 年,最火的可能就是 openAI 了,其组织代表的产品 chatGTP,相信大家已经有所耳闻.不少同学已经开始着手使用,并截图晒出 ChatGPT 是多么得智能与神奇.而有的同学在使 ...