Proxy实现vue MVVM实践
栏目: JavaScript · 发布时间: 5年前
内容简介:vueconf(2018hangzhou)大会刚刚过去,vue作者尤大大向我们展示了vue3.0的进展,并介绍vue3.0的一些改动,其中最令我期待的就是重写数据监听机制。谈起vue的双向数据绑定,我们首先能想到的就是ES5中我们就针对
vueconf(2018hangzhou)大会刚刚过去,vue作者尤大大向我们展示了vue3.0的进展,并介绍vue3.0的一些改动,其中最令我期待的就是重写数据监听机制。
回顾vue2.x的双向数据绑定
谈起vue的双向数据绑定,我们首先能想到的就是ES5中 Object.defineProperty
,利用重写属性的 get
、 set
,我们可以完成数据劫持监听,使用观察者模式,在数据发生改变的时候,通知订阅者更新状态。
我们就针对 Observer
观察者部分写了一个简易的代码如下:
function Observer (data) { this.data = data this.walk(data) } Observer.prototype = { walk: function (data) { let me = this Object.keys(data).forEach(function (key) { me.convert(key, data[key]) }) }, convert: function (key, val) { this.defineReactive(this.data, key, val) }, defineReactive: function (data, key, val) { let dep = new Dep() let childObj = observe() Object.defineProperty(data, key, { enumerable: true, configurable: false, get: function () { if (Dep.target) { dep.depend() // 添加订阅者 } return val }, set: function (newVal) { if (newVal === val) return val = newVal childObj = observe(newVal) dep.notify() // 通知订阅器 } }) } } function observe (value, vm) { if (!value || typeof value !== 'object') { return } return new Observer(value) } 复制代码
以上代码中我们定义了一个 Observer
构造函数,即观察者。利用 Object.defineProperty
我们将传入对象的所有属性(包含子属性)全部进行数据监听,并在 get
方法中,在订阅器里添加一条订阅。一旦某属性发生改变,通知到订阅器。
Dep订阅器,Compile指令,Watcher订阅者的代码就不再分析,mvvm的总体结构可以由下图看出
整个过程是一个观察者、订阅器、订阅者、指令器四部分的事情,各司其职。
简单介绍Proxy
Proxy是ES6中新增的构造函数,它可以理解为在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤改写。Proxy原意是代理,在这里我们可以理解为“代理”某些操作。
var obj = new Proxy({}, { get: function (target, key, receiver) { console.log(`proxy get ${key}`) return Reflect.get(target, key, receiver) }, set: function (target, key, value, receiver) { console.log(`proxy set ${key}`) return Reflect.set(target, key, value, receiver) } }) 复制代码
上面代码对一个空对象架设了一层拦截,我们可以在Proxy的第二个参数中传入一个 handler
对象,对象中可以定义拦截行为。
在 get
和 set
中,我们都用到了 Reflect
。 Reflect
对象与 Proxy
对象一样,也是ES6位了操作对象而提供的新API。 Reflect
对象的方法与 Proxy
对象的方法一一对应,比如 Proxy
方法拦截 target
对象的属性赋值行为。它采用 Reflect.set
方法将值赋值给对象的属性,确保完成原有的行为,然后再部署额外的功能。
根据以上代码我们写一段测试代码:
obj.text = 'hello world!' // proxy set text var _text = obj.text // proxy get text 复制代码
Proxy改写观察者
利用以上 Proxy
的一些特性,我们修改代码如下:
function observe (value, vm) { if (!value || typeof value !== 'object') { return } let dep = new Dep() return new Proxy(value, { get: function (target, key, receiver) { if (Dep.target) { dep.depend() } return Reflect.get(target, key, receiver) }, set: function (target, key, value, receiver) { dep.notify() return Reflect.set(target, key, value, receiver) } }) } 复制代码
我们将传入的对象直接替换为 Proxy
对象,入参 handler
的 get
和 set
中的添加订阅者和通知订阅器逻辑保持不变。
整个过程没有做其他多余的判断,由于Vue3.0还没有发布,没有实际源码可以借鉴,所以以上只是个人实现的简单版本( 完整代码 )。将整个mvvm运用到html中,以下是运行后的效果(没做gif,凑合看吧):
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Flutter实践——实现一个动态页
- Redis 实现发布订阅原理与实践
- GAN入门实践(二)--Pytorch实现
- GAN入门实践(一)--Tensorflow实现
- 应用XGboost实现多分类模型实践
- [实践总结]纯css实现动态边框
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。