详解vue的双向绑定原理及实现

使用vue也好有一段时间了,虽然对其双向绑定原理也有了解个大概,但也没好好探究下其原理实现,所以这次特意花了几晚时间查阅资料和阅读相关源码,自己也实现一个简单版vue的双向绑定版本,先上个成果图来吸引各位:

代码: 效果图:

详解vue的双向绑定原理及实现

详解vue的双向绑定原理及实现

是不是看起来跟vue的使用方式差不多?接下来就来从原理到实现,从简到难一步一步来实现这个SelfVue。由于本文只是为了学习和分享,所以只是简单实现下原理,并没有考虑太多情况和设计,如果大家有什么建议,欢迎提出来。

本文主要介绍两大内容:

1. vue数据双向绑定的原理。

2. 实现简单版vue的过程,主要实现{{}}、v-model和事件指令的功能。

相关代码地址:https://github.com/canfoo/self-vue

vue数据双向绑定原理

vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的,那么vue是如果进行数据劫持的,我们可以先来看一下通过控制台输出一个定义在vue初始化数据上的对象是个什么东西。

代码:

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

结果:

详解vue的双向绑定原理及实现

我们可以看到属性a有两个相对应的get和set方法,为什么会多出这两个方法呢?因为vue是通过Object.defineProperty()来实现数据劫持的。

Object.defineProperty( )是用来做什么的?它可以来控制一个对象属性的一些特有操作,比如读写权、是否可以枚举,这里我们主要先来研究下它对应的两个描述属性get和set,如果还不熟悉其用法,。

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

var Book = { name: 'vue权威指南' }; console.log(Book.name); // vue权威指南

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

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

我们通过Object.defineProperty( )设置了对象Book的name属性,对其get和set进行重写操作,顾名思义,get就是在读取name属性这个值触发的函数,set就是在设置name属性这个值触发的函数,所以当执行Book.name = 'vue权威指南' 这个语句时,控制台会打印出 "你取了一个书名叫做vue权威指南",紧接着,当读取这个属性时,就会输出 "《vue权威指南》",因为我们在get函数里面对该值做了加工了。如果这个时候我们执行下下面的语句,控制台会输出什么?

console.log(Book);

结果:

详解vue的双向绑定原理及实现

乍一看,是不是跟我们在上面打印vue数据长得有点类似,说明vue确实是通过这种方法来进行数据劫持的。接下来我们通过其原理来实现一个简单版的mvvm双向绑定代码。

思路分析

实现mvvm主要包含两个方面,数据变化更新视图,视图变化更新数据:

详解vue的双向绑定原理及实现

关键点在于data如何更新view,因为view更新data其实可以通过事件监听即可,比如input标签监听 'input' 事件就可以实现了。所以我们着重来分析下,当数据改变,如何更新视图的。

数据更新视图的重点是如何知道数据变了,只要知道数据变了,那么接下去的事都好处理。如何知道数据变了,其实上文我们已经给出答案了,就是通过Object.defineProperty( )对属性设置一个set函数,当数据改变了就会来触发这个函数,所以我们只要将一些需要更新的方法放在这里面就可以实现data更新view了。

详解vue的双向绑定原理及实现

思路有了,接下去就是实现过程了。

实现过程

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/fd087dc0b2ed87654b4e395285c7c384.html