我正在参加「创意开发 投稿大赛」详情请看:掘金创意开发大赛来了!
实现一个observer方法
监听对象特定的属性,当被监听的属性发生变化的时候才触发回调函数打印输出,如果修改的是没有被监听的属性则不处理。
observer() 方法接收三个参数:
1. obj: 要监听的对象 Object 比如: {a: 1}
2. [path]: 要监听对象特定的属性路径 [String], 比如: ["obj.a"]
3. cb: 监听到指定属性变化时的回调函数,返回新值和旧值
思路分析
-
核心部分当然是 Object.defineProperty 劫持对象,在set方法里判断如果值发生改变,则调用 回调函数cb()
-
遍历 path 数组,只对指定的属性进行劫持,没有指定的属性不做处理
-
对 path 里的路径进行处理,从对象里获取到对应的属性值。
- 👉这里要注意,深层级的路径要递归处理,递归传参要搞清楚 ❗
SHOW MY CODE
function observer(obj, path, cb) {
path.forEach((key) => {
let value = "";
if (key) {
const _key = key.split(".");
if (_key.length > 1) {
let tmp = obj;
// 循环,为了取到属性值,不断地赋值给 tmp
_key.forEach((k) => {
// 递归,对每一个层级都进行劫持,要不然无法监听到深层级的属性值变化
observer(tmp, [k], cb);
tmp = tmp[k];
});
value = tmp;
} else {
value = obj[key];
}
Object.defineProperty(obj, key, {
get() {
return value;
},
set(newV) {
if (newV !== value) {
cb && cb(newV, value);
value = newV;
}
},
});
}
});
}
var o = {
a: 1,
b: 2,
c: {
x: 1,
y: 2,
},
};
observer(o, ['a',"c.x"], (v, prev) => {
console.log("newV=", v, " oldV=", prev);
});
o.a = 2; // 2, 1
o.b = 3; // 不打印
o.c.x = 3; // 3, 1
o.c.y = 3; // 没有没监听,不打印
打印:劫持后的 obj
可以发现属性值以及被Getter/Setter转化了
小结
-
Object.defineProperty 是高频使用的语法,Vue2 里面借助这个实现了很多功能,比如:data数据穿透,computed、methods等方法的代理,响应式原理…… 需要重点掌握的知识。
-
递归: 抽象思维,复杂问题简单化,代码更简洁。递归三要素👇
-
明确你这个函数想要干什么
-
寻找递归结束条件
-
找出函数的等价关系式
-
🎈🎈🎈
🎉 喜欢的小伙伴可以点赞收藏关注
✨ 欢迎大家转发评论交流, 蟹蟹😊