实现Vue中的Getter
- 在HTML文件中引入自己创建的vue.js.
- 在vue.js中定义Vue类和构造函数.
- vue.js中定义一个数据劫持的方法
- 使用Object.keys(obj).forEach获取对象所有的键。
下面是html结构
<body>
<div id="app">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
</div>
<script src="./vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
name: '张三',
age: 20,
info: {
a: 'a1',
c: 'c1'
}
}
});
console.log(vm);
</script>
</body>
下面是我们自建的vue.js文件:
class Vue {
constructor(options) {
this.$data = options.data;
// 调用数据劫持的方法
Observe(this.$data);
}
}
// 定义一个数据劫持的方法
function Observe(obj) {
Object.keys(obj).forEach((key) => {
let value = obj[key];
Object.defineProperty(obj,key,{
enumerable: true,
configurable: true,
get() {
console.log(`有人获取${key}的值`);
return value;
},
set(newVal) {
value = newVal
}
})
})
}
上面的Observer函数存在一个问题,就是只将对象的第一层属性添加了getter和setter,却没有对深层次的属性添加,因此下面使用递归解决这个问题。
使用递归为对象上的所有属性添加getter和setter
// 定义一个数据劫持的方法
function Observe(obj) {
// 递归结束条件
if (!obj || typeof obj !== 'object') {
return;
}
Object.keys(obj).forEach((key) => {
let value = obj[key];
Observe(value);
Object.defineProperty(obj,key,{
enumerable: true,
configurable: true,
get() {
console.log(`有人获取${key}的值`);
return value;
},
set(newVal) {
value = newVal
}
})
})
}
主要就是看从哪里开始递归,以及递归的终止条件是什么。
上面的Observe函数还存在着一个问题,那就是加入为对象的属性赋值会覆盖掉原本的setter和getter。
为新赋值的对象也添加getter和setter
为了解决上面提到的问题,我们在调用属性的setter方法时,也需要再次将对象投入Observe递归中。
// 定义一个数据劫持的方法
function Observe(obj) {
// 递归结束条件
if (!obj || typeof obj !== 'object') {
return;
}
Object.keys(obj).forEach((key) => {
let value = obj[key];
Observe(value);
Object.defineProperty(obj,key,{
enumerable: true,
configurable: true,
get() {
console.log(`有人获取${key}的值`);
return value;
},
set(newVal) {
value = newVal
Observe(value)
}
})
})
}
总结
要想给vue实例上的data进行数据劫持,需要考虑数据类型,递归,getter和setter时什么时候调用递归等等问题。