vue的双向绑定原理

参考:http://www.cnblogs.com/canfoo/p/6891868.html
vue实现双向数据绑定的原理是利用了Object.defineProperty()这个方法重新定义对象获取属性get()方法和设置属性set()方法来实现数据劫持。

Object.defineProperty(obj,prop,descriptor)

  • obj 要在其上定义属性的对象
  • prop 要定义或修改的属性的名称
  • descriptor 将要被定义或修改的属性描述符

在平常,我们可以很容易的打印出一个对象的属性数据

    var book = {
      name: 'JavaScript高级程序设计'
    }
    console.log(book.name);  //JavaScript高级程序设计

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

	var Book = {};
    var name = '';
    Object.defineProperty(Book,'name',{
      set: function(value){
        name = value;
        console.log('这本书的名字叫' + value); //这本书的名字叫JavaScript高级程序设计
      },
      get: function() {
        return '《'+ name +'》'
      }
    })
    Book.name = 'JavaScript高级程序设计'; 
    console.log(Book.name);//《JavaScript高级程序设计》

访问属性时,执行get()方法;修改/设置属性时,执行set()方法。由于我们在get()方法里return的时候加上了书名号,所以在console.log(Book.name)时该书名就会带上书名号

想要实现mvvm,包含两个方面:数据变化更新视图,视图变化更新数据。
那么当数据更新时,要如何更新视图呢?首先我们要思考 如何知道数据变了,由以上例子可知,可以通过Object.defineProperty()对属性设置set()函数,当数据改变时会触发该方法。
现在,我们来实现数据双向绑定

  1. 实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。
  2. 实现一个订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。
  3. 实现一个解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。

1、实现一个监听器Observer

   function defineReactive(data, key, val) {
      observe(val); // 递归遍历所有子属性
      Object.defineProperty(data, key, {
        enumerable: true,
        configurable: true,
        get: function() {
            return val;
        },
        set: function(newVal) {
            val = newVal;
            console.log('属性' + key + '已经被监听了,现在值为:“' + newVal.toString() + '”');
        }
      });
    }
    function observe(data) {
      if (!data || typeof data !== 'object') {
        return;
    }
      Object.keys(data).forEach(function(key) {
        defineReactive(data, key, data[key]);
      });
    };
 
    var library = {
      book1: {
        name: ''
      },
      book2: ''
    };
    observe(library);
    library.book1.name = 'vue权威指南'; // 属性name已经被监听了,现在值为:“vue权威指南”
    library.book2 = '没有此书籍';  // 属性book2已经被监听了,现在值为:“没有此书籍”

猜你喜欢

转载自blog.csdn.net/qq_43553067/article/details/88859229