双向数据绑定所需前置知识
1. 数组的reduce方法
数组的reduce方法的使用场景一般是本次操作的初始值需要依赖上次操作的返回值,例如数值的累加,链式获取对象属性的值。
reduce函数接收两个参数:
- 函数(之前的累积值,当前遍历到的元素的值)
- 初始值
函数体中要返回之前的累积值和当前遍历的值的和
const arr = [1,2,3,4];
let res = arr.reduce((pre,cur) => {
return pre + cur;
},0)
console.log(res); // 10
通过reduce链式获取对象属性的值
const obj = {
name: '张三',
info: {
address: {
location: '北京怀柔'
}
}
}
const arr = ['info','address','location'];
const location = arr.reduce((pre,cur) => pre[cur],obj);
console.log(location); // 北京怀柔
2. 发布订阅模式
发布订阅模式中主要包含下面两个类:
- Dep类
- 负责进行依赖收集
- 有一个数组,用来存放所有的订阅信息
- 有一个向数组中添加订阅的方法
- 提供一个循环,循环出发数组中的每个订阅信息
- Watcher类
- 负责订阅事件
下面是最基本的Dep类和Watcher类:
// Dep类主要是收集订阅
class Dep {
constructor() {
// subs数组,用于存放所有订阅者的信息
this.subs = []
}
// 向subs数组中,添加订阅者的信息
addSub(watcher) {
this.subs.push(watcher);
}
// 发布通知的方法
notify(){
this.subs.forEach(watcher => {
watcher.update();
})
}
}
// 订阅者的类
class Watcher {
constructor(cb) {
this.cb = cb;
}
// 触发回调的方法
update() {
this.cb();
}
}
const w1 = new Watcher(() => {
console.log('这是第一个订阅者');
})
const w2 = new Watcher(() => {
console.log('这是第二个订阅者');
})
const dep = new Dep();
dep.addSub(w1);
dep.addSub(w2);
dep.notify()
订阅者我们可以理解为DOM元素,当数据发生变化的时候,Vue会通知到每一个订阅者,然后订阅者根据最新的数据更新DOM。
3. 使用Object.defineProperty()进行数据劫持
- 通过get()劫持取值操作。
- 通过set()劫持赋值操作。
const obj = {
name: '张三',
age: 20,
info: {
a: 1,
b: 2
}
}
Object.defineProperty(obj,'name',{
enumerable: true,
configurable: true,
get() {
console.log('有人获取了obj.name的值');
return "获取的是这里的张三"
},
set(newVal) {
console.log('打印出新的值');
}
})
console.log(obj.name);
obj.name = '555';
console.log(obj);