0
点赞
收藏
分享

微信扫一扫

#yyds干货盘点#这一次,彻底搞懂双向数据绑定02

实现Vue中的Getter

  1. 在HTML文件中引入自己创建的vue.js.
  2. 在vue.js中定义Vue类和构造函数.
  3. vue.js中定义一个数据劫持的方法
  4. 使用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时什么时候调用递归等等问题。

举报

相关推荐

0 条评论