分类 Vue 下的文章

Vue 双向数据绑定之原理及实现 4


Vue 双向数据绑定之原理及实现 1
Vue 双向数据绑定之原理及实现 2
Vue 双向数据绑定之原理及实现 3

一、Compiler解析器

解析器的作用一方面是解析出视图中相关的指令,将数据填充到视图中,另一方面也是添加新的订阅者,在数据发生更新时,能同步更新到视图中。
有了解析器以后,整个模型就算是完整了,参考下图:
双向数据绑定完整模型

Vue中的模板指令非常多,而且也做了很多的兼容,所以我们这只做例如v-model, {{}}, v-on
基本思路:

1、把真实DOM元素转换为文档片段;
2、遍历文档片段中所有的节点,解析出双括号指令和v-xxx的指令;
3、根据不同的指令,添加不同的操作:
    v-model: 初始化数据,添加订阅器,同时添加input事件;
    v-text: 初始化数据,添加订阅器;
    v-on: 为当前元素节点添加对应的事件和回调;







Vue双向数据绑定之原理及实现3


一、实现原理

1. 从数据到视图的更新,是需要对数据进行监听劫持,这里我们设置一个监听器Observer来实现对所有数据的监听;

2. 设置一个订阅者Watcher,收到属性的变化通知并执行相应的函数,从而更新视图;

3. 设置一个解析器Compiler,解析视图DOM中所有节点的指令,并将模板中的数据进行初始化,然后初始化对应的订阅器。

二、Observer监听器

Observer是一个数据监听器,核心是Object.defineProperty(),对所有属性监听,利用递归来遍历所有的属性值,对其进行Object.defineProperty()操作。


Vue双向数据绑定之原理及实现2


一、数据代理

我们封装的代码中,进行数据访问是myVue.data.name,而实际Vue中的如果要获取数据肯定不需要添加data选项即 myVue.namemyVue.skill
此时就可以通过代理,将data数据选项绑定在Vue对象中,修改时同步到data。

function Vue(options){    
    this.el = options.el        // 元素
    this.data = options.data     // 数据
    this.watcher = {}    // 属性、数据、元素 的关联
    
    var self = this 
    Object.keys(this.data).forEach(function(key){    // 遍历所有key
        self.proxyKeys(key); // 添加代理(data项的处理)
        self.defineProperty(self.data, key, self.data[key])    
    })
    
    // 解析DOM
    this.compile()    
}

Vue.prototype = {
    proxyKeys(key){
        var self = this 
        Object.defineProperty(this, key, {
            enumerable: false,
            configurable: true,
            get(){
                return self.data[key]
            },
            set(newVal){
                self.data[key] = newVal
            }
        })
    },
      
    // defineProperty、compile保持不变
    // ...
}


Vue双向数据绑定之原理及实现1


还是否记得第一次使用Vue时的感觉?双向数据绑定,竟然那么神奇,可以让代码变的如此简单。

一、Vue核心思想

在了解Vue的双向绑定之前,你先要回忆一下Vue的核心思想。还记得getter/setter方法、还记得Watcher?
Vue核心思想

关于getter/setter方法

1.当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项 (图中就是 a 对象中的 b 属性,即 a.b),Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter 方法。
2. 用户看不到 getter/setter 方法,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
3. 同时 Vue 会对模板进行编译,解析之后会生成指令对象,也例如 v-text, v-hide 等。当指令中 v-text='a.b'时,其实就是触发 getter 方法,获取对应的数据。

另外每个属性都对应有一个 Watcher,它有什么作用?

1.当 data 选项中 a.b 值发生改变时,就会触发 setter 方法,会通知到对应的 watcher。
2. 之后再通知指令去调用 update 方法,由于指令是 DOM 的封装,所在在 update 时其实就是调用了原生 javascript 的 DOM 方法来更新界面。