操作数据,页面会随之改变。
实现原理:
Vue在组件和实例初始化的时候,会将data里的数据进行数据劫持(object.definepropty对数据做处理)。被劫持后的数据会有两个属性:一个叫getter,一个叫setter。[在生成vue实例时,为对传入的data进行遍历,使用Object.defineProperty把这些属性转为getter/setter.]
getter是使用数据的时候触发,setter是在修改数据的时候触发,修改数据的时候触发setter,同时也触发了底层的watcher监听,通知dom修改刷新。
每个vue实例都有一个watcher实例,它会在实例渲染时记录这些属性,并在setter触发时重新渲染。
export default {
name: "test",
components: {},
data() {
return {
data0:{
name:"yyp"
}
}
},
methods: { },
mounted: function () {
let data1 ={name:1};
console.log("初始化时就定义的的name,会有getter和setter属性:",this.data0);
console.log("初始化后新定义的name,没有getter和setter属性:",data1);
Object.defineProperty(data1,'age',{
get(){},
set(){}
});
console.log("被Object.defineProperty处理过的data,age属性有getter和setter属性:",data1)
},
created(){ }
}
三次console.log的结果如下:

image.png
Object.definepropty
是es5中的一个方法,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。处理数据,给数据赋予getter和setter。
正常情况下,这两个方法都不会触发,当我们给数据赋值和改变值的情况下会执行这两个函数。
let middle = 6
Object.defineProperty(data,'age',{
get(){
console.log('获取age')
return middle
},
set(parmas){
//参数就是赋值的数据
console.log('修改age数据',parmas)
middle = parmas
}
})
// 取值的时候触发getter
console.log(data.age)
//赋值的时候触发setter
data.age = 15
console.log(data.age)
Vue中数据变页面一定变嘛?
先来看一个小例子:
<div id ='app'>
{{user}}
<hr>
<button @click='changeName'>changeName</button>
</div>
<script>
new Vue({
el:'#app',
data:{
user:{
age:15
}
},
methods: {
changeName(){
this.user.name = '韩梅梅'
console.log(this.user)
}
},
})
</script>
这时候点按钮,发现改变不了name的值,所以打开控制看一下

image.png
我们会发现只有age有getter和setter,name没有,Vue 无法检测到对象属性的添加或删除,所以没法进行响应式改变数据。
Vue 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value)方法向嵌套对象添加响应式属性。
两种情况新添加的属性都有没有getter和setter,数据变页面也不变:
- 对象数据的添加
- 数组长度的改变
解决方式:动态的往里面添加数据,使用this.$set方法
methods: {
changeName(){
// this.user.name = '韩梅梅'
// set 将数据用 object.defainPropty进行处理 添加getter和setter
this.$set(this.user,'name','韩梅梅')
console.log(this.user)
}
}
这样我们就能在页面上看到新增的属性

image.png