尝试使用es6新特性,自己来实现一个mvvm及vue的各种特性。
相关代码放在github,会持续更新,欢迎赏个star。
本篇文章为系列文章的第一篇,会比较容易理解,后续会持续更新后面的记录。
最简单的watcher
从开始接触Vue开始,我们便对它的“数据响应”赞叹不绝,那么我们首先,来实现一个最简单的watcher,来监听数据,以进行对应的操作,类似后续会涉及的dom操作等。
Proxy
我们都知道,Vue使用Object.defineProperty来进行数据监听,监听obj的get和set方法。在ES6中,Proxy可以拦截某些操作的默认行为,也就是对目标对象的访问进行拦截,过滤和改写。我们可以利用这个特性来实现对数据的监听:
|
|
结果:
|
|
简单的Dom操作
我们已经可以对简单的数据操作进行监听(虽然还有各种问题),接下来,我们只要在监听到dom后进行数据操作即可。解析模板什么的我们就先不做了,我们可以继续利用Proxy实现一个dom辅助函数:
|
|
也就是说,我们为dom的各属性进行监听,当访问对应的节点时,我们创建并且为他添加各种属性等:
|
|
拼接基础框架
我们在这里给我们的这个小架子起名为’W’,让它可以真正的运行起来。类似Vue的语法,我们需要在进行实例化的时候,watch我们的data,并且更新dom。类似这样:
|
|
因此,我们需要实现这样一个类,来处理我们的参数,并进行实例的初始化,监听,以及渲染控制等。
|
|
初始化数据
首先,我们进行数据初始化,将数据置为observable,在对其修改的时候进行监听:
|
|
在这里我们需要注意两点:
- 我们的data参数为一个function
这个原因在vue官方文档已经说过,当我们直接使用对象的时候,不同的实例间会共享同一个对象,导致出现对一个组件进行修改,另一个组件也进行修改的问题。
具体可以查看data-必须是函数
- 我们返回的是this._vm而不是this
我们这里做了两步操作,首先将this与data进行合并,再将整个对象进行监听,并赋值到_vm属性上。
这样,我们通过new W()初始化的实例,则可以访问到我们的data属性及方法,并且具有数据驱动的特性了。
更新DOM
我们已经为watcher的回调添加了dom更新的事件,我们只要在这里执行render函数,并挂载到对应的el上即可:
|
|
绑定this
我们会发现,我们在config的render函数中,使用了this.msg来访问data的msg属性,因此我们需要实现在各组件中,通过this可以访问到本实例的特性。我猜你已经想到了,我们可以使用bing,call和apply来实现它:
|
|
测试
简单的架子拼接完成,我们来进行测试下我们的成果,我们需要实现两点功能:
- 可以按照我们的render函数正常挂载,并可访问到data上的数据
- 通过对实例进行修改,修改会自动更新到节点上
代码:
结果:
最基本的功能已经实现啦!
结语
本次我们只实现了最最最简单的数据驱动功能,后续还有很多需要进行处理,我们也会对其一一进行梳理和实现,大家可以持续关注下,例如:
- 数组变动监听
- object深度监听
- 更新队列
- render过程中记录仅相关的属性
- 模板渲染
- v-model
- …等等
敬请期待!