本文共 1568 字,大约阅读时间需要 5 分钟。
双向数据绑定
个人笔记,如有错误请见谅。
Vue.js的做法是采用数据劫持加发布者订阅模式,通过object.defineproperty()来劫持各个属性的getter与setter方法,setter监听值改变,getter返回改变后的值,在数据变动的时候,object.property()的set方法监听数据,通过get方法返回修改后的数据,通过Dep.notify方法通知订阅者(watcher),让订阅者去攻击视图更新数据。
模拟vue代码主要实现三件事
实现一个指令解析器Complie
实现一个数据监听器 Observer
实现一个Watcher去更新视图
实现一个proxy代理
实现complie
准备模板

在Mvue.js文件中

上面的querySelector前加上document.

可以看到我们已经绑定了模板以及Mvue类。
接着需要遍历节点对其进行数据替换
每个都进行替换监听会引起页面的不断重毁和回流,这时候借助文档碎片对象,将其放入内存中减少重绘回流。


使用for of 遍历模板所有节点

接着再一个一个放入文档碎片钟


可以看到左边的节点已经在文档碎片对象中了

接着将节点追加到要插入的元素之中,即app

接着我们要在模板解析出来之前去编译。
所以我们先别追加。在追加前进行编译。

将所有元素节点取出来了。

注意,我们这只是遍历第一层,故要判断
有些模板有指令如v-mode,v-html,v-text,可以通过指令判断实现相对应操作。
先获取这个节点上的属性,里面就有指令
通过node.attributes来获取

通过强制转化为数组并且将其值遍历出来

我们只需要v-开头的属性,所以做个判断


我们需要通过dirname的不同做出不同的判断,需要用到策略模式
策略模式()


通过对象里面定义属性:方法来做出相对应的操作。

接着将先将模板加载到app里

可以看到,实现了模板编译的功能了。

也有一些值绑定的是A.A

更新数据之后记得删除属性哦

小总结:
对文本节点的编译 文本节点就是这些{
{}} 

。。。arg里面是个数组,第1个值就是去掉{
{}}的数据,

##接着就是绑定事件了

指向的不是window 
处理v-bind

处理语法糖


至此,所有的编译解析功能实现完毕。
总结
解析编译,创建一个Vue类,将数据绑定在构造函数之上,并且在new一个Complie对象,去解析模板。所以要创建一个Complie对象,在Complie对象构造函数中,首先通过传进来的ID去获取模板,并创建一个文件对象,将模板里的节点取出来放进文件对象。再解析文件对象,将所有节点取出来,并且判断是元素节点(v-mode那些)还是文本节点{
{input}}那些,再做不同的操作。对元素结点的操作,获取属性attributes通过split,赋值解构等方法获取html,test,on,model等,通过策略模式,创建一个新类A,并在类里面定义几个方法,分别对应html,test,mode,on,bind等。然后通过调用A[‘test’](节点,属性值,Vue实例,事件名称 ),因为在一开始Vue的构造函数绑定了数据,故通过Vue.$data[属性值]即可获取相应内容,通过InnerHTML等方法赋值给节点,实现编译。 对于事件方法,只需要在一开始new Vue时,记得给methods加入方法,这样在A类的on里面就可以通过node.addEventListener(事件名,Vue.$methods.data.bind(Vue))来做出相对应的判断,记得方法要改变this指向。
对于bind,也是一样,node[属性]=Vue.$data.属性值,就可以动态绑定属性。
语法糖只是多做了几步判断,
并不难实现。
转载地址:http://sexn.baihongyu.com/