理解vue数据响应式
响应式 : 当data中的数据发生改变时 , 视图中的数据也会跟着改变
一 抛出问题
在vue中的data中定义一个空对象 , 将来动态给对象添加属性 , 改变这个属性
具体看代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!-- 添加视图容器 -->
<div id="app">
<h3>渲染age属性</h3>
<div>{{ obj.age }}</div>
<div><button @click="changeAge">点我修改 age 的值</button></div>
<h3>渲染 name 属性</h3>
<div>{{ obj.name }}</div>
<div>
<button @click="setName">点我动态添加 name 属性</button>
</div>
</div>
</body>
<script src="../vue.min.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
obj: {
age: 18
}
},
methods: {
changeAge() {
this.obj.age = 20
},
setName() {
// 非响应式 只会给obj添加name属性及属性值 , 但视图没有更新
// this.obj.name = 'xjj'
// 响应式
this.$set(this.obj, 'name', 'xjj')
}
}
})
// 响应式:
// 当 data 中的数据发生改变时, 视图中的数据也会跟着改变
// 什么情况下属性不会有响应式的效果:
// 在 data 中的数据下动态添加属性是不会有响应式的效果
</script>
</html>
当更改的属性name在data中并没定义 , 这个时候触发更改name , 实质只会给data中添加了该属性和值 , 但视图没有动态更新
这个属性之所以没有在视图响应式渲染出来 , 是因为它是动态添加的
在data中的数据下动态添加属性是不会有响应式的效果
二 引出推论
动态给 data 中对象添加属性,是不会有响应式的效果的
三 解决方案
set可以实现动态为data中的对象添加具有响应式效果的属性
四 $set的具体用法
引述vue文档
向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新
用法:
Vue.set( target, key, value )
调用方法:this.$set( target, key, value )
//参数
target:要更改的数据源(可以是对象或者数组)
key:要更改或者新增属性的具体数据 (对象的key为键,数组的key为下标)
value :重新赋的值
官方解释:向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。
应用场景:
需要为data对象添加一个新属性时或修改某个属性的值时,却没有更新到视图上,这个时候就用$set解决
上述 , 可以简单理解如下
语法
// target: 响应式的对象
// protoName: 属性名(要向响应式对象中添加的属性)
// value: 属性值
Vue.set(target, protoName, value)
// 上例中
this.obj.name = 'xjj'
// target: obj
// protoName: name
// value: xjj
五 总结
<1> vue实例创建之后添加新的属性到实例上,它不会触发视图更新
=> 当生成vue实例后,这时对vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)再次给对象添加新属性并赋值时(向对象中添加新的属性及属性值),并不会自动更新到视图上去
解析:
受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时进行双向数据绑定,使用Object.defineProperty()对属性遍历添加 getter/setter 方法,因此 Vue.js 在初始化实例时将属性转为 getter/setter,
所以属性必须在 data 对象上存在时才能进行上述过程 , 让 Vue.js 转换它,才能让它是响应的。
如果要给对象添加新的属性,此时新属性没有进行过上述过程,它不是响应式的。
此时需要用到$set。
<2> Vue.set()不光能修改数据,还能添加数据
使用$set()方法,既可以为data数据模型这个对象里的属性=>新增属性(并且给这个属性赋值)或修改原有属性的值,同时可以触发视图更新
<3> 因此,$set可以理解为重新给data数据模型中的某个属性(可以是对象或者数组下的某层属性)重新赋值,无论是新增的属性或者原有的属性,都可以给他更改值,达到视图响应式更新的目的
举例
// 给数组中的对象的添加原有属性的值(给group这个数组下的满足find条件的对象的option属性下拉框添加数据,这个是数据为数组AccList)
this.$set(this.formConfigJson.formItems[0].group.find(item => item.key === 'accPayment'), 'options', this.AccList)
作者:春秋若北
链接:https://www.jianshu.com/p/092e3de6ef0a
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。