解读vue实例的双向绑定源码

vue是一个渐进式的基于MVVM执行数据操作的纯前端JavaScript框架。

一、首先来了解下什么是MVVM?

MVVM(Model—View—ViewModel)模式,分为三块:

1. Model:模型数据,保存着实例所有数据的对象-----data,包含着业务逻辑。

2. View:视图,整个界面的布局和外观。

3. ViewModel:视图模型,扮演View和Model的‘使者’,将视图和模型绑定,实现View的业务逻辑。

二、vue数据双向绑定原理

原理:主要通过Object.defineProperty()方法来进行数据劫持以及配合发布者-订阅模式来实现的。

1. Object.defineProperty():

var vm = new Vue({
    data: {
        obj: {a: 1}
    },
    created() {
        console.log(this.obj);
    }
});

可以看到属性a有两个相对应的get和set方法,为什么会多出这两个方法呢?因为vue是通过Object.defineProperty()来实现数据劫持的。它可以来控制一个对象属性的一些特有操作,比如读写权、是否可以枚举,这里我们主要先来研究下它对应的两个描述属性get和set。

2. 数据劫持:当vue实例化的时候,会去遍历所有的属性,给这些属性加上getset方法来进行数据劫持(重写data的get、set方法)。

3. 发布者-订阅模式:https://www.jianshu.com/p/2ec316ca0f8b

三、具体实现:

  前面说到通过数据劫持实现双向绑定,执行数据劫持前,需要先监听数据是否发生改变(observer监听器);监听到有改变时需要告知订阅者是否需要改变(watcher订阅者),同时当有很多订阅者时,需要一个管理器来管理众多订阅者(Dep订阅管理器);紧接着我们还要有个指令解析器来对每个节点进行扫描和解析(解析节点的指令如v-on),把他们初始化成一个订阅器Watcher,并且绑定相应的函数(compile指令解析器),Watcher会对比前后两个的数值是否发生变化,然后确定是否通知视图进行重新渲染。

这个图应该更清晰些:

 需要做的:

1. 实现一个监听器Observer,用来劫持并监听所有属性,如果有变动,就通知订阅者。

2. 实现一个订阅者Watcher,用来接收监听器的属性变化通知,并执行相应函数,做到视图更新。

3. 实现一个订阅者管理器Dep,用来管理众多订阅者。

4. 实现一个解析器Compile,用来扫描解析每个节点的相关指令,初始化模板数据以及订阅者。


四、先来认识下Object.defineProperty()方法实现数据劫持(改写方法)

// 正常获取一个对象的属性
var Book = {
  name: 'vue权威指南'
};
console.log(Book.name);  // vue权威指南

如果要在执行console.log(book.name)的同时,直接给书名加个书名号,那要怎么处理呢?或者说要通过什么监听对象 Book 的属性值。这时候Object.defineProperty( )就派上用场了,代码如下:

let Book = {};
let name = '';
Object.defineProperty(Book,'name',{
    set(value){
        name = value;
        console.log('你命名了一个书名:'+value);
    },
    get(){
        return '《'+name+'》'
    }
});
Book.name = 'vue权威指南' ; // 你命名了一个书名:vue权威指南
console.log(Book.name); // 《vue权威指南》

 // 未完待续

参考:https://www.jianshu.com/p/5fe2664ff5f7

参考:https://www.cnblogs.com/libin-1/p/6893712.html

参考:https://segmentfault.com/a/1190000014274840#comment-area

猜你喜欢

转载自www.cnblogs.com/xiong88/p/12721985.html
今日推荐