Vue2数据双向绑定的原理(Object.defineProperty)

        首先我们得了解一些MVVM模型, Vue的作者在看到MVVM模型之后, 受到了启发, 开发出了Vue中所特有的模型.

        M: 代表着模型层(Model) 就是data中的数据(一般js对象), V: 代表着视图层(View) 就是DOM元素, VM: 代表着模型层和视图层的链接桥梁 也就是Vue实例.

        Vue2数据双向绑定的原理(Object.defineProperty)_第1张图片

        从这个图中间的两个箭头可以看出来, Vue总共做了两件事:

  • 将data中的数据(一般js对象, 因为data中renturn出来了一个对象), 建设到了DOM元素上.
  • 监听DOM的改变动态的修改data中的数据.

        我们在data中定义的成员都会被挂载到Vue的实例Vm上面, 只要在模板(template)里面进行修改data中的数据, 都会触发视图的改变.

        但是这是有一个前提的, 就是data中所有的成员都需要通过Object.defineProperty进行事件属性拦截, 简答的来说就是他通过Object.defineProperty这个属性将说有成员设置成响应式的.

现在就来介绍一下Object.definProperty:

  • 第一个参数: 需要动态添加成员的对象(target)
  • 第二个参数: 动态添加到目标对象(target)上的属性(property)
  • 第三个参数: 配置项(description), 其中有enumerable、configurable、writable、value、get和set定义的对象.

不要着急哈, 现在来一点一点的了解:

  • 先来对比一下动态添加的属性, 和直接将属性写入对象中有什么区别

Vue2数据双向绑定的原理(Object.defineProperty)_第2张图片

Vue2数据双向绑定的原理(Object.defineProperty)_第3张图片

        很容易的可以看出两个"age"属性颜色是不同的, 使用Object.defineProperty方法添加的是不可以枚举的.

        枚举的意思就是不能被遍历的, 举个栗子:

直接添加:

 Vue2数据双向绑定的原理(Object.defineProperty)_第4张图片

Vue2数据双向绑定的原理(Object.defineProperty)_第5张图片

 Vue2数据双向绑定的原理(Object.defineProperty)_第6张图片

 动态添加:

Vue2数据双向绑定的原理(Object.defineProperty)_第7张图片

 Vue2数据双向绑定的原理(Object.defineProperty)_第8张图片

 

  • 再来说一下enumerable、configurable、writable、value这几个成员是如何使用的:
  1. value是动态添加那个属性的属性值
  2. enumerable将它的属性这设置为true的话, 那么动态添加的属性就允许枚举, 默认为false
  3. configurable将它的属性这设置为true的话, 那么动态添加的属性就允许删除, 默认为fasle
  4. writable将它的属性这设置为true的话, 那么动态添加的属性就允许修改, 默认为false

        上述来看, Object.defineProperty条条框框的很多, 很麻烦的样子; 其实不然, 它是一种高级的用法, 可以对属性添加控制.

        不像手动添加属性那样随意, 我们可以对属性更好的控制.

  • 现在就要开始着重的介绍set和get属性了, 数据代理和computed计算属性都是使用的这个底层原理来实现的, 上代码:



  
  
  
  Document


    
我是订阅者

Vue2数据双向绑定的原理(Object.defineProperty)_第9张图片

原理: 

Vue 数据双向绑定原理是通过 数据劫持 + 发布者-订阅者模式 的方式来实现的,首先是通过 ES5 提供的 Object.defineProperty() 方法来劫持(监听)各属性的 getter、setter,并在当监听的属性发生变动时通知订阅者,是否需要更新,若更新就会执行对应的更新函数。

什么是数据劫持

数据劫持比较好理解,通常我们利用Object.defineProperty劫持对象的访问器,在属性值发生变化时我们可以获取变化,从而进行进一步操作。

发布者模式 / 订阅者模式

在软件架构中,发布订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在。同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者(如果有的话)存在。

这里很明显了,区别就在于,不同于观察者和被观察者,发布者和订阅者是互相不知道对方的存在的,发布者只需要把消息发送到订阅器里面,订阅者只管接受自己需要订阅的内容

你可能感兴趣的:(前端,javascript,vue.js)