vue响应式原理

2 篇文章 0 订阅
1 篇文章 0 订阅

最近看了一篇文章讲的是vue响应式的实现原理,复述一下吧~

文章参考:https://mp.weixin.qq.com/s/v8eT3WGolbabXDI24Ybx9Q
或许还没有原文说的清楚,可能有理解错的地方,欢迎大佬路过敲打~
只是单纯按照原文打了一遍代码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')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值