什么是响应式?
这是一个比较模糊的概念。通常可以理解成对某些操作有所反应。比如响应式网页就是网页内容对窗口大小的变化有所反应,根据窗口大小动态改变网页内容。
Vue的数据响应式指的是数据发生变化时,UI对这种变化有所反应,即会更新UI。
Object.defineProperty()
监听
Vue实现数据响应式主要使用JS的Object.defineProperty(),该API可以设置属性的getter\setter。从而实现监听数据。
let obj = { name: "feng" };
let _name = obj.name;
Object.defineProperty(obj, "name", {
get() {
console.log("您获取了name属性值");
return _name;
},
set(value) {
console.log("您设置了name属性值");
_name = value;
},
});
使用Object.defineProperty()对name进行劫持后,之后对name属性的读写操作都是走getter或setter。那么我们就可以在getter和setter中通知UI,UI从而进行更新。
代理
Object.defineProperty()还可以实现代理功能。当我们使用data数据时,都是this.name的形式调用的。此时就产生疑问了?this指的是Vue实例,怎么就能读写我们定义的data呢?答案就是Vue代理了data。
let obj = { name: "feng" };
function proxy(data) {
//监听
let _name = data.name;
Object.defineProperty(data, "name", {
get() {
console.log("您获取了name属性值");
return _name;
},
set(value) {
console.log("您设置了name属性值");
_name = value;
},
});
//代理
const obj = {};
Object.defineProperty(obj, "name", {
get() {
return data.name;
},
set(value) {
data.name = value;
},
});
return obj;
}
//此处可看成const vm = new Vue(options)
let vueInstance = proxy(obj);
//此时就可以通过vue实例去访问name属性
console.log(vueInstance.name);
this.$set()和Vue.set()
通过上述内容,可以发现想要对数据进行劫持,那么数据一开始就要有属性。换句话说,对于数据后添加的属性,Vue是监听不到的。那么就无法实现数据响应式、更新UI了。因此Vue提供了两个API应对这种情况。
- this.$set()
- Vue.set()
这两个API其实是一样的,都是指向同一个函数即this.$set === Vue.set表达式的值是true。
- 参数一:要修改的对象
- 参数二:修改的属性
- 参数三:属性值
{
data(){
return {
obj:{
name:'feng'
}
}
},
methods:{
setAge(){
//设置新增的属性
this.$set(this.obj,'age',18)
}
}
}