Skip to content

解决vue修改数据页面不重新渲染问题(Vue中数组和对象更改后视图不刷新(转载) ​

本节目标:理解“解决vue修改数据页面不重新渲染问题(Vue中数组和对象更改后视图不刷新(转载)”的核心思路,并能把它用于实际开发或面试表达。

说明:原 OneNote 中有图片引用,但图片未包含在导出目录中;本页保留了可用的文字与代码内容。 Luck Young 2020-07-07 15:08:10

219

收藏 1 分类专栏: 前端 Vue 版权 vue渲染机制和如何解决数据修改页面不刷新问题的多种方法 本文不讲原理,只讲干货易懂易学,(感觉能学到知识,麻烦给小编来个赞!)

  1. 简单介绍一下Object.definePropety,==Object.defineProperty(obj, prop, descriptor)========//参数========obj========要在其上定义属性的对象。========prop========要定义或修改的属性的名称。========descriptor========将被定义或修改的属性描述符========var obj = {}========Object.defineProperty(obj, 'name', {====== ==get: function() {====== ==console.log('我的名字叫'+name);====== ==return name;====== ==},====== ==set: function(value) {====== ==console.log('你叫'+value)====== ==name = value;====== ==}========});========obj.name ='张三';==//你叫张三======obj.name==//我的名字叫张三====

  2. ==1==

  3. ==2==

  4. ==3==

  5. ==4==

  6. ==5==

  7. ==6==

  8. ==7==

  9. ==8==

  10. ==9==

  11. ==10==

  12. ==11==

  13. ==12==

  14. ==13==

  15. 因此在vue中写在data中的属性是是可以转换成getter和setter,换一句话就是响应式的,其他定义在data之外的数据,是无法响应的渲染,意思就是改变数据页面也不会刷新,所以一切要渲染到页面上的数据,必须写在data中,不需要的,可以定义在this上,==var vm = new Vue({====== ==data:{====== ==a:1====== ==}========})==========// vm.a 是响应式的==========vm.b = 2======// vm.b 是非响应式的====

  16. ==1==

  17. ==2==

  18. ==3==

  19. ==4==

  20. ==5==

  21. ==6==

  22. ==7==

  23. ==8==

  24. ==9==

  25. ==10==

  26. 简单介绍完了,我们来列举几个不刷新的实例当然上述也是一种第一种:修改对象的某一属性vue只会将已经在data中声明的属性变为响应,没有声明的是不响应的==<template>====== ==<div>====== ==<div v-for='item in list'>{{item}}</div>====== ==<button @click='click'>改变</button>====== ==<button @click='hadelClick'>解决方法</button>====== ==</div>========</template>========<script>====== ==export default({====== ==data(){====== ==return{====== ==list:{a:'a',b:'b'},====== ==}====== ==},====== ==methods: {====== ==click() {====== // 未声明不触发渲染==== ==this.list.c='c'============},====== ==hadelClick(){====== // 解决方法,使用vue提供的$set方法来触发渲染==== ==this.$set(this.list,'d','d')====== ==}====== ==}====== ==})========</script>======

  27. ==1==

  28. ==2==

  29. ==3==

  30. ==4==

  31. ==5==

  32. ==6==

  33. ==7==

  34. ==8==

  35. ==9==

  36. ==10==

  37. ==11==

  38. ==12==

  39. ==13==

  40. ==14==

  41. ==15==

  42. ==16==

  43. ==17==

  44. ==18==

  45. ==19==

  46. ==20==

  47. ==21==

  48. ==22==

  49. ==23==

  50. ==24==

  51. ==25==

  52. ==26==

  53. ==27======当然如果我们要添加多个属性,可以使用 Object.assign() 用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,并返回目标对象。(简单说就是合并到第一个参数中)==this.list = Object.assign({},this.list,{c:'c',d:'d'})======第二种:修改数组对象的某一属性==<template>====== ==<div>====== ==<div v-for='item in list'>{{item.a}}</div>====== ==<button @click='click'>改变</button>====== ==<button @click='hadelClick'>解决方法</button>====== ==</div>========</template>========<script>====== ==export default({====== ==data(){====== ==return{====== ==list:[{a:'vue'},{a:'react'},{a:'js'}],====== ==}====== ==},====== ==methods: {====== ==click() {====== //想这样直接给数组中的某一个对象直接赋值,是无法动态渲染的(即改变了数据,页面不渲染)==== ==this.list[0] = {a:'css'}== //页面不渲染==== ==console.log(this.list)== //[{a:'css'},{a:'react'},{a:'js'}]==== ==},====== ==hadelClick(){====== // 解决方法,使用vue提供的$set方法来触发渲染==== ==this.$set(this.list[1],'a','css')====== ==console.log(this.list)==//[{a:'css'},{a:'css'},{a:'js'}]==== ==}====== ==}====== ==})========</script>======

  54. ==1==

  55. ==2==

  56. ==3==

  57. ==4==

  58. ==5==

  59. ==6==

  60. ==7==

  61. ==8==

  62. ==9==

  63. ==10==

  64. ==11==

  65. ==12==

  66. ==13==

  67. ==14==

  68. ==15==

  69. ==16==

  70. ==17==

  71. ==18==

  72. ==19==

  73. ==20==

  74. ==21==

  75. ==22==

  76. ==23==

  77. ==24==

  78. ==25==

  79. ==26==

  80. ==27==

  81. ==28======当然前文讲过,vue会遍历data中的数据,将对象转换成setter和getter。所以数组中的也不例外,所以上述操作_// 改成:_======click(){====== ==this.list[0].a = css== //依旧能够触发setter。实现数据重新渲染==== ==}========}======

  82. ==1==

  83. ==2==

  84. ==3==

  85. ==4==

  86. ==5==

在vue中更多的是数组的操作不刷新,一种是通过索引赋值,一种是修改数组长度,如何解决呢? vue官方也给了方法 数组的API,中能够改变原始数组的都能触发更新; ==Array.push()========Array.pop()========Array.shift()========Array.unshift()========Array.splice()========Array.sort()========Array.reverse()======

  • ==1==
  • ==2==
  • ==3==
  • ==4==
  • ==5==
  • ==6==
  • ==7==

第二种是返回一个新数组的,这种数组在引用地址上已经发生根本改变,这样的赋值操作是能触发更新的(这是处理不刷新的思路,就是改变引用地址,重新赋值触发更新) 简单说,用数组的API就是直接用原数组接收改变的数组, ==<template>====== ==<div>====== ==<div v-for='item in list'>{{item.a}}</div>====== ==<button @click='click'>改变原数组</button>====== ==<button @click='hadelClick'>不改变原数组</button>====== ==</div>========</template>========<script>====== ==export default({====== ==data(){====== ==return{====== ==list:[{a:'vue'},{a:'react'},{a:'js'}],====== ==}====== ==},====== ==methods: {====== ==click() {====== //改变数组刷新页面==== ==this.list.push({a:'css'})====== ==},====== ==hadelClick(){====== //重新赋值刷新页面 ==== ==this.list = this.list.map(item=>{====== ==item.a = 'css'====== ==return item====== ==})====== ==}====== ==})========</script>======

  • ==1==
  • ==2==
  • ==3==
  • ==4==
  • ==5==
  • ==6==
  • ==7==
  • ==8==
  • ==9==
  • ==10==
  • ==11==
  • ==12==
  • ==13==
  • ==14==
  • ==15==
  • ==16==
  • ==17==
  • ==18==
  • ==19==
  • ==20==
  • ==21==
  • ==22==
  • ==23==
  • ==24==
  • ==25==
  • ==26==
  • ==27==
  • ==28==

最后提供解决思路(以上都搞不定的话) 对象和数组都是引用传递,要变成新数组,来接受,就需要改变源, 第一种 ==let arr = []==//新数组======this.list.forEach(item=>{== //需要渲染的数组==== //执行你的操作,最后用放到arr中==== ==arr.push(item)========})========this.list = arr== //相当于返回一个新数组可以触发渲染====

  • ==1==
  • ==2==
  • ==3==
  • ==4==
  • ==5==
  • ==6==

第二种 //想要直接改变渲染数组中的数据,但没有渲染====//解决方法:======let arr = this.list.slice(0);==//深拷贝,(等价一个新的数组)======arr.forEach(item=>{====== //执行你的操作======})======//赋值操作======this.list = arr======

  • ==1==
  • ==2==
  • ==3==
  • ==4==
  • ==5==
  • ==6==
  • ==7==
  • ==8==

当然这里只是简单介绍了,有关深拷贝的详细介绍,请参看另一篇博文 js数组深拷贝详解 上述如果都无法执行,但你的数据缺实修改了,可以使用this.$forceUpdate()方法 (强制刷新) // this.$forceUpdate(); // 强制刷新======<template>== ==== ==<div>====== ==<div v-for='item in list'>{{item.a}}</div>====== ==<button @click='click'>改变</button>====== ==<button @click='hadelClick'>解决方法</button>====== ==</div>========</template>========<script>====== ==export default({====== ==data(){====== ==return{====== ==list:[{a:'vue'},{a:'react'},{a:'js'}],====== ==}====== ==},====== ==methods: {====== ==click() {====== ==this.list[0] = {a:'css'}== //页面不渲染==== ==console.log(this.list)== //[{a:'css'},{a:'react'},{a:'js'}]==== ==},====== ==hadelClick(){====== ==this.list[0] = {a:'css'}== //页面不渲染==== ==console.log(this.list)== //[{a:'css'},{a:'react'},{a:'js'}]==== ==this.$forceUpdate();==//强制刷新==== ==}====== ==}====== ==})========</script>======

  • ==1==
  • ==2==
  • ==3==
  • ==4==
  • ==5==
  • ==6==
  • ==7==
  • ==8==
  • ==9==
  • ==10==
  • ==11==
  • ==12==
  • ==13==
  • ==14==
  • ==15==
  • ==16==
  • ==17==
  • ==18==
  • ==19==
  • ==20==
  • ==21==
  • ==22==
  • ==23==
  • ==24==
  • ==25==
  • ==26==
  • ==27==
  • ==28==

———————————————— 版权声明:本文为CSDN博主「MmM豆」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/marendu/article/details/93492642 > 来自 <https://blog.csdn.net/Mote123/article/details/107181531/?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-3>

首先 第一点,vue底层是 将data对象传人,使用Object.definePropety,转换为getter和setter,所以,vue不支持IE8. 从上述我们可以简单发现。当我们对这个对象的name属性赋值的时候,就会触发set方法,获取name属性的时候就会触发get方法; > 来自 <https://blog.csdn.net/Mote123/article/details/107181531/?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-3>

本站总访问 — 次