前言

在开发过程中,我们时常会遇到这样一种情况:当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的。

根据官方文档定义:如果在实例创建之后添加新的属性到实例上,它不会触发视图更新

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter

受现代 JavaScript 的限制 (以及废弃 Object.observe),Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。

对象

看一下示例:

在vue框架中,如果data中有一个变量:age,修改他,页面会自动更新。但如果data中的变量为数组或对象,我们直接去给某个对象或数组添加属性,页面是识别不到的

<template>
<p>{{userInfo.name}}</p>
<p v-if="userInfo.sex">{{userInfo.sex}}</p>
<button @click="updateName">修改userInfo</button>
<button @click="addSex">添加性别</button>
</template>
<script>
data(){
userInfo:{name:'小明'}
},
methods:{
updateName(){
this.userInfo.name='小红'
},
addSex(){
this.userInfo.sex = '男'
}
}
</script>

可以发现,在updateName函数中,我们尝试给userInfo对象修改name值,并成功修改,但添加的sex属性失败了

分析

  • 名字修改成功是因为vue初始化时为对象的属性建立 了getter/setter函数,可以监测数据变化并挂载到视图上
  • 而新增的sex属性由于错过了建立getter/setter阶段,即使在userInfo对象中添加成功,但由于没有setter函数,无法响应到视图上

解决方法

方法一:$forceUpdate()

迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。

methods:{
updateName(){
this.userInfo.sex='男'
this.$forceUpdate();
}
}

方法二:Vue.set(object, key, value)

methods:{
updateName(){
this.$set(this.userInfo,'sex,'男');
}
}

数组

上面的例子反映的是给对象添加属性时的问题,数组同样有类似的问题,请看下面的例子

<body>
<div id="app">
<p>{{userInfo.name}}</p>
<p v-if="userInfo.sex">{{userInfo.sex}}</p>
<ul>
<li v-for="(item,index) in hobbies" :key='index'>{{item}}</li>
</ul>
<button @click="update">修改爱好</button>
</div>
<script>
let vm = new Vue({
el:'#app',
data: {
userInfo:{name:'小明'},
hobbies:['抽烟','喝酒','烫头']
},
methods:{
update(){
this.hobbies[2] = '读书'
}
}
})
</script>
</body>

点击修改爱好按钮后页面并没有修改,打开控制台发现值已修改

解决方法

一、使用vue提供的更新数组的方法

vue给我们提供了它封装后的可用于对数组进行增删改查操作的方法

Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

上面的例子

update(){
//参数分别是:开始索引,是否删除(0:添加 1:删除),修改后的值
this.hobbies.splice(2,1,'读书')
},

使用封装后的方法则可以成功渲染到视图

二、Vue.set()

update(){
//参数分别是:对象,索引,修改后的值
Vue.set(this.hobbies,2,'读书')
},

三、this.$forceUpdate()

 update() {
this.hobbies[2] = '读书'
this.$forceUpdate()
},

最新文章

  1. geotrellis使用(十二)再记录一次惨痛的伪BUG调试经历(数据导入以及读取瓦片)
  2. 纯HTML+CSS带说明的黄色导航菜单
  3. soui使用wke时,设置js回调注意事项
  4. 【bzoj1211】 HNOI2004—树的计数
  5. gcc-gdb
  6. 关于ASP .Net Core 引用dll 一
  7. React文档翻译 (快速入门)
  8. 【Beta阶段】第三次scrum meeting
  9. 调用awk的三种方式
  10. 如何接入银联“快速接入”产品API
  11. [Android] Android 使用 FragmentTabHost + Fragment 实现 微信 底部菜单
  12. python-爬虫(3)---lxml匹配css
  13. Python获得百度统计API的数据并发送邮件
  14. RestFul风格API(Swagger)--从零开始Swagger
  15. BZOJ4669抢夺(费用流+二分答案)
  16. GreenDao设置数据版本
  17. VMware Workstation11安装Mac OS X 10.10虚拟机
  18. finecms如何批量替换文章中的关键词?
  19. oracle 11g用exp无法导出空表的解决方案
  20. [uboot]在uboot里面添加环境变量使用run来执行

热门文章

  1. phpstoem破解
  2. cgroup配置
  3. c++ 的学习笔记 第一集cim cout
  4. Chrome浏览器启动参数大全(命令行参数)
  5. 踩坑系列《一》数据库建表权限 CREATE command denied to user for table
  6. Java中的基本类型和包装类
  7. 使用寄存器点亮LED——2
  8. wget命令8种实用用法
  9. 更好的 java 重试框架 sisyphus 的 3 种使用方式
  10. 吴恩达深度学习课后习题第5课第1周第3小节: Jazz Improvisation with LSTM