- 真正使用vue的时候,给属性赋值,获取属性值,都是直接使用Vue实例
// es5中的方法
Object.defineProperty(对象,'设置什么属性名',{
configurable:true/false, 是否是可配置的
writable:true/false, 是否是可编辑的
enumerable: true/false, 控制属性是否可枚举,是不是可以被 for-in 取出来
set(){}, 赋值触发
get(){}, 取值触发,
value:
})
注意:
writable和get/set 是没办法同时存在的
let o ={};
o.name = 'zs';
等价于下面的写法:
Object.defineProperty(o,'name',{
configurable: true,
writable: true,
enumerable: true,
value: 'zs'
})
将对象处理成响应式的
原理:其实就是使用Object.defineProperty() 对数据进行处理,将数据编程响应式的
<script>
let o = {};
o.name = 'zs';
let _age;
Object.defineProperty(o,'age',{
configurable: true,
enumerable: true,
get: function() {
return _age;
},
set: function(newVal) {
_age = newVal;
}
});
// 注意:如果同时使用get与set需要使用一个中间变量存储数据
/**
上面代码存在的问题:
1、将 _age 暴露在全局
*/
// 将对象转换为响应式的
let obj = {
name: 'zs',
age: 20,
gender: '女'
}
function defineProperty(target,key,value,enumerable) {
// 在这里相当于使用了 闭包 ,因为 value 是在函数内部使用的
Object.defineProperty(target,key,{
configurable: true,
enumerable: !!enumerable,
get: function() {
console.log(`获取${key}的值`);
return value;
},
set: function(newVal) {
console.log(`设置${key}的值为:${newVal}`);
value = newVal;
}
})
}
// 将对象处理成响应式的
let keys = Object.keys(obj);
for (let i = 0; i < keys.length; i++) {
defineProperty(obj,keys[i],obj[keys[i]],true);
}
</script>
/*
上面代码存在的问题:
1、只能将简单的数据进行响应式处理,像对象里面嵌套对象,数组里面嵌套对象,这种情况是没办法实现数 据响应式的
*/
// 解决上面代码存在的问题,添加 reactify 函数
function reactify(obj) {
let keys = Object.keys(obj);
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
let val = obj[key];
/**
需要判断这个属性的属性值,是否是引用类型(也就是对象数据类型object),是否是数组类型
1、如果是引用数据类型,需要调用defineReactive 将数据响应式化
2、如果是数组类型,需要循环遍历数组,然后将数组里面的元素响应式化
*/
if(Array.isArray(val)) {
for(let j = 0; j < val.length; j++) {
reactify(val[j]);
}
} else {
defineReactive(obj,key,val,true);
}
}
}
reactify(obj);