深入响应性原理
终于到了讲解我们 Vue 的响应式原理,前面我们已经讲解了 Map,WeakMap,Set,WeakSet,Proxy,Reflect 这几个知识点。那么接下来思考下到底什么是响应式,就比如我们做一个公司的官网,然后要求必须兼容手机端,ipad 端,电脑端,内容屏幕大小变化而变化,这些就需要依赖 JavaScript,CSS, HTML 去处理了。
那么假如我们像在 Excel 表格中,两个数字相加,如果一个数字变化了,两个数字的和肯定得变化吧,Excel 表格做到了,可定里面是做了很大的处理了,那如果使用 JavaScript 来做,我们该如何做呢?
`let var1 = 2
let var2 = 3  
let sum = var1 + var2
// 当 var1 变化时,
// 该如何通知 sum
`
如果我们更新第一个值,sum 不会被修改。
那么我们如何用 JavaScript 实现这一点呢?
检测其中某一个值是否发生变化
用跟踪 (track) 函数修改值
用触发 (trigger) 函数更新为最新的值
Vue 如何追踪变化?
在 Vue 中,在将一个对象数据传递给一个组件的时候,Vue 已经给我这些数据设置了 setter,getter 属性,一旦数据发生变化,就会得到响应,这其中就是 Proxy,Reflect 的很大的功劳。
通过前面的知识,我们知道 Proxy 是一个包含另一个对象或函数并允许你对其进行拦截的对象。
let obj = {       var1: 2,       var2: 3,       sum: 0,   }   let handlerObj = {       get(target, prop) {           if(prop == 'sum') {               target['sum'] = target['var1'] + target['var2']               return target['sum']           }           return target[prop]       },       set(target, prop, newVal) {           target[prop] = newVal       }   }   let p = new Proxy(obj, handlerObj)   console.log(p.sum)   

此外,Proxy 还提供了另一个特性。我们不必像这样返回值:target[prop],而是可以进一步使用一个名为 Reflect 的方法,它允许我们正确地执行 this 绑定,就像这样:  
let obj = {       var1: 2,       var2: 3,       sum: 0,   }   let handlerObj = {       get(target, prop) {           if(prop == 'sum') {               target['sum'] = target['var1'] + target['var2']           }           return Reflect.get(...arguments)       },       set(target, prop, newVal) {           target[prop] = newVal       }   }   let p = new Proxy(obj, handlerObj)   console.log(p.sum)   

上面我们已经检测到了哪些数据发生了变化,所以接下来我们需要用一个我们还没实现的 track 追踪方法来进行修改:  
let obj = {       var1: 2,       var2: 3,       sum: 0,   }   let track = (target, prop) => {       if(prop == 'sum') {           target['sum'] = target['var1'] + target['var2']       }   }   let handlerObj = {       get(target, prop) {           track(target, prop)           return target[prop]       },       set(target, prop, newVal) {           target[prop] = newVal       }   }   let p = new Proxy(obj, handlerObj)   console.log(p.sum)   

最后,当某些内容发生改变时我们会设置新的值。为此,我们将通过触发这些更改来设置新 Proxy 的更改:
let obj = {       var1: 2,       var2: 3,       sum: 0,   }   let track = (target, prop) => {       if(prop == 'sum') {           target['sum'] = target['var1'] + target['var2']       }   }   let trigger = (target, prop, newVal) => {       target[prop] = newVal   }   let handlerObj = {       get(target, prop) {           track(target, prop)           return target[prop]       },       set(target, prop, newVal) {     trigger(target, prop, newVal)                      return Reflect.set(...arguments)       }   }   let p = new Proxy(obj, handlerObj)   console.log(p.sum)   

当某个值发生变化时进行检测:我们不再需要这样做,因为 Proxy 允许我们拦截它
跟踪更改它的函数:我们在 Proxy 中的 getter 中执行此操作,称为
effect触发函数以便它可以更新最终值:我们在 Proxy 中的 setter 中进行该操作,名为
trigger
本文分享自微信公众号 - 人生代码(lijinwen1996329ken)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
 
 
 
 
 
 