Vue 双向绑定原理浅析

参考

  • Vue.js
  • MDN

一、 vue 双向数据绑定语法

Vue.js作为前端MVVM三大框架之一,最核心的功能便是数据的双向绑定了,Vue使用HTML的模版语法实现了ViewModel。Vue开发者们可以使用“Mustache”语法 (双大括号)来将数据解析成文本,也可以使用v-model等特性指令来实现数据的双向绑定。

二、 v-model的原理和应用

在开发过程中,我们经常使用v-model指令在表单元素上创建双向数据绑定。比如:


而实际的含义是:

 

所以,v-model相当于通过v-bind向子组件传递prop,然后通过子组件的事件监听来更新父组件的值。那么,清楚了v-model的语法,我们也可以使用v-model来实现一个双向数据绑定的组件。下面是官方文档的一个例子:

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    
  `
})

至此,我们已经可以自己封装一个双向数据绑定的组件了,v-model就是vue的双向数据绑定的原理了吗?显然不是的!

三、 真•核心原理:数据劫持

大家都知道,要想实现双向数据绑定,v-model传入的参数须是data属性里的变量,否则还是无法实现双向绑定的效果。那么,data定义的变量和普通声明的变量究竟有何区别?

  data () {
    return {
      test: {
        a: 1
      }
    }
  },
  mounted () {
    console.log(this.test)
  }

控制台输出的结果:

console.png

我们可以看到test Object的a属性带有getter和setter两个function。可以看出vue data定义的变量的属性是由Object.defineProperty()添加的,同时Object.defineProperty()也实现了vue的数据劫持。下面代码中,我们给a赋值触发了setter,然而setter并没有把value赋值给a,所以a的值还是undefined,我把这种现象理解为数据劫持。

使用Object.defineProperty()定义一个test Object:

var test = {};
Object.defineProperty(test, 'a', {
    set: function reactiveSetter(value) {
        console.log('set a ...');
    },
    get: function reactiveGetter() {
        console.log('get a ...');
    }
});
test.a = 1;
console.log(test);
console.log(test.a);

控制台输出结果:


console.png

可以看到Object.defineProperty()定义的test和data定义的test相同。而且,我们在给test.a赋值的时候会触发setter,获取test.a时会触发getter。所以我们可以在setter里通过事件来驱动View的更新,结合v-model 的DOM事件驱动数据更新就可以达到双向数据绑定的效果了。

你可能感兴趣的:(Vue 双向绑定原理浅析)