文章参考:mp.weixin.qq.com/s/v8eT3WGol… 或许还没有原文说的清楚,可能有理解错的地方,欢迎大佬路过敲打~ 只是单纯按照原文打了一遍代码o(╥﹏╥)o
想以买东西为模型来进行响应式,想达到的目标是改变数量总价可以随之改变
/**
* @price 单价
* @num 数量
* @total 总价
*
*/
复制代码
1.完全不能实现目标
let price = 2;
let num = 3;
let total = price * num;
console.log(total, 'total1')
num = 5;
console.log(total, 'total2')
复制代码
2.有点希望,先将有关的变化的值的操作(target函数)存到一个数组中(storage),每当相关变量变化时(数量变化时)手动调用
let price = 2;
let num = 3;
let total = 0;
let target = null;
let storage = []; // 记录标记函数的
function record() {
storage.push(target);
}
function replay() {
storage.forEach(run => run())
}
target = () => {
total = price * num;
}
record()
replay()
console.log(total, 'total1')
num = 5;
replay()
console.log(total, 'total2')
复制代码
我们可以根据需要继续记录目标, 但是有一个更强大的解决方案可以扩展我们的应用程序。 那就是一个负责维护目标列表的类,当我们需要它们重新运行时, 这些目标列表会得到通知。 解决方法: 使用Class 我们可以开始解决这个问题的一种方法是将这种行为封装到它自己的Class中,这是一个实现标准编程观察者模式的依赖类。
3.虽然实现了观察者的类,但是还是需要手动执行订阅函数,而且在类内还有着外部变量,这是程序员所不能忍的
class Dep {
constructor() {
this.subscribers = []; // 存储变化值操作的函数
}
depend() { // 依赖
this.subscribers.push(target) // 将操作函数压入数组
}
notify() { // 通知
this.subscribers.forEach(sub => sub()) // 在接收到通知时 执行操作函数
}
}
const dep = new Dep();
let price = 2;
let num = 3;
let total = 0;
target = () => {
total = price * num;
}
dep.depend()
dep.notify()
console.log(total, 'total1')
num = 5;
dep.notify()
console.log(total, 'total2')
复制代码
将外部变量传参进入函数中封装起来 但是还是留下了全局变量target来进行信息的传递 wacher中进行赋值 并且调用dep来进行存储 依旧是手动触发
class Dep {
constructor() {
this.subscribers = []; // 存储变化值操作的函数
}
depend() { // 依赖
this.subscribers.push(target) // 将操作函数压入数组
}
notify() { // 通知
this.subscribers.forEach(sub => sub()) // 在接收到通知时 执行操作函数
}
}
const dep = new Dep();
let price = 2;
let num = 3;
let total = 0;
function wacher(myFunction) {
target = myFunction;
dep.depend();
target();
target = null;
}
wacher(() => {
total = price * num;
})
console.log(total, 'total1')
num = 7;
dep.notify()
console.log(total, 'total2')
复制代码
现在只有一个Dep类,但我们真正想要的是每个变量都有自己的Dep
let data = {
price: 2,
num: 5
}
let temp = data.num;
Object.defineProperty(data, 'num', { // defineProperty使用方法
get() {
console.log('getNum');
return temp;
},
set(val) {
console.log('setNum');
temp = val;
}
})
复制代码
对对象中的所有数据执行递归加set/get 所以找到了可以在每个变量里加dep的方法
Object.keys(data).forEach(key => {
let temp = data[key];
Object.defineProperty(data, key, {
get() {
console.log(`get${key}`)
return temp
},
set(val) {
console.log(`set${key}`)
temp = val
}
})
});
复制代码
4.实现了一个简易版的数据跟踪
let data = {
price: 2,
num: 5
}
let total = 0
let target = null
class Dep {
constructor() {
this.subscribers = []
}
depend() {
if(target && !this.subscribers.includes(target)) {
this.subscribers.push(target)
}
}
notify() {
this.subscribers.forEach(sub => sub())
}
}
Object.keys(data).forEach(key => {
let temp = data[key]
const dep = new Dep()
Object.defineProperty(data, key, {
get() {
dep.depend()
return temp
},
set(val) {
temp = val
dep.notify()
}
})
})
function wacher(myFunction) {
target = myFunction
target()
target = null
}
wacher(() => {
total = data.price * data.num
})
console.log(total, 'total1')
data.num = 88
console.log(total, 'total2')
data.price = 77
console.log(total, 'total3')
复制代码