当vue的data里面声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象添加新的属性,如果更新此属性的值,是不会更新视图的。
根据官方文档定义:如果在实例创建之后添加新的属性到实例上,它不会触发视图更新
原理:当你把一个普通的javascript对象传入Vue实例作为data选项,Vue将遍历此对象所有的属性,并使用Object.defineProperty把这些属性全部转为getter/setter
受现代javascript的限制(以及废弃Object.observe),Vue不能检测对象属性的添加或者删除。由于Vue会在初始化实例是对属性执行getter/setter转化过程,所以属性必须在data对象上存在才能让Vue转换它,这样才能让它是响应的。
实例:

  1. <template>
  2. <view class="content">
  3. <text @click="addd(obj)">{{obj.d}}</text>
  4. <text @click="adde(obj)">{{obj.e}}</text>
  5. </view>
  6. </template>
  7. <script lang="ts">
  8. import moment from 'moment';
  9. moment.locale("zh-cn");
  10. import Vue from "vue";
  11. export default Vue.extend({
  12. data(){
  13. return{
  14. obj:{}
  15. }
  16. },
  17. mounted(){
  18. this.obj= {d:0};
  19. this.obj.e=0;
  20. console.log('after--',this.obj);
  21. },
  22. methods:{
  23. addd(item: any){
  24. item.d=item.d+1;
  25. console.log('item--',item);
  26. },
  27. adde(item: any){
  28. item.e = item.e+1;
  29. console.log('item--',item);
  30. }
  31. }
  32. });
  33. </script>

image.png
点击触发3次addd,点击触发3次adde,页面效果及控制台信息如下:
image.png
image.png
此时我们触发一次addd,页面效果如下:
image.png
image.png
很明显,我们可以看出,更新新增属性e,是不会更新视图,但是会改变其值,当更新原有的属性d时才会更新视图,同时将新增的属性e的值也更新导视图里边。

解决方案

官方定义:Vue不允许在已经创建的实例上动态添加新的根级响应式属性(root-level reactive property)。然后而他可以使用Vue.set(object,key,value)方法将响应属性添加到嵌套的对象上:

Vue.set(vm.obj,’e’,0)
你还可以使用vm.$set实例方法,这也是全局Vue.set方法的别名:

this.$set(this.obj,’e’,02)

有时你想向已有的对象上添加一些属性,例如使用Object.assign()或_.extend()方法来添加属性。但是,添加到对象上的新属性不会触发更新。在这种情况下可以创建一个新的对象,让它包含原对象的属性和新的属性。
//代替Object.assign(this.obj,{a:1,e:2})
this.obj=Object.assign({},this.obj,{a:1,e:2})

上述实例解决方案如下:
image.png
点击触发三次addd,点击触发三次adde,页面效果及控制台信息如下:
image.png
image.png