问题来了
现在Vue 是目前比较流行的前端框架,也是经常会被问到的问题,我们知道vue中的双向数据绑定是一大亮点,当数据发生改变了,也会通知我们的视图随之而更改,那么问题来了,数据一发生改变,视图咋就知道要改变了呢?
知识铺垫
在解密这个之前,我们需要先了解下Object.defineProPerty,接下来咱们就先来看下这个知识。
Object.defineProPerty 是Object类的私有属性,所以大家需要注意的是,我们对象实例是不能用这个方法的。
具体语法:
var obj={};
// 给对象 obj 添加一个属性名 name,属性值是 “lili”
Object.defineProperty(obj,"name","lili");
除了上面的写法,对于值我们还可以写成对象的形式:
Object.defineProperty(obj,"name",{
value:"li",
// 可枚举,默认是不可枚举
enumerable:true,
// 是否可删除
configurable:true,
// 是否可修改
writable:true
});
有时候我们想要在获取或者得到value值的时候做一些操作,那我们还可以把value 省去,添加上get 函数和 set 函数
Object.defineProperty(obj,"name",{
//value:"li",
// 每次获取值的时候,就会进到get函数里面,return 是多少,咱们取到的值就是多少
get(){
return 100
},
// 每次设置值的时候,就会进到这个set 函数里面,设置的值会传进来
set(newValue){
console.log(newValue)
},
//可枚举
enumerable:true,
// 是否可删除
configurable:true,
// 是否可修改
writable:true
});
如果想要设置值的时候,能让get 里面的返回值发生改变,我们可以借助第三个变量
var _use="";
Object.defineProperty(obj,"name",{
//value:"li",
get(){
return _use
},
set(newValue){
_use=newValue;
},
//可枚举
enumerable:true,
// 是否可删除
configurable:true,
// 是否可修改
writable:true
});
真正的揭秘开始了
截止到这里,我们需要了解的知识已经够了,接下来,我们还是回到最初的问题,想下数据改变了,怎么才能知道呢,其实vue2.0 就是用的Object.defineProperty 的数据劫持,只要一更改数据,就会触发set 函数,这里我们就可以来一个劫持。接下来让我们看下如果去写吧
// 模拟vue 中的data
var data={
message:"hello",
job:[{name:"web"}]
};
// 每次在初始化的时候,为了实现拦截,我们需要把data 里面的数据都拿到,然后用Object.defineProperty 一个个添加属性,让它有get 和set 函数,在这里我们先封装这样一个方法
// 初始的时候先调用下这个函数,然后把最初的data里面的属性都添加上get 和set
function observe(data){
if(typeof data!="object"){
return data;
}
for( var key in data){
define(data,key,data[key]);
}
}
function define(obj,key,value){
// 如果传递进来的值是多层结构的,为了保证里层的数据也加上get set 所以我们统一再执行下observe
observe(value);
Object.defineProperty(obj,key,{
get(){
return value;
},
set(newValue){
if(newValue !=value){
console.log("视图发生改变了!");
value= newValue;
}
}
})
}
observe(data);
//data.message="hehe";
// data["job"][0].name="hehe";
data["job"][0].name="b";