Vue应用的是mvvm框架,view和model分离,然后通过vm双向数据绑定,`

<!-- 模板 -->
<div id="app">
    {{msg}}
</div>
<!-模型->
// 原生对象即数据
var data = {
    msg: 'hello!'
}
// 创建一个 ViewModel 实例
var vm = new Vue({
    // 选择目标元素
    el: '#app',
    // 提供初始数据
    data: data
})

然而一个动态数据的绑定,是怎么实现的呢,首先Vue利用es5的defineProperty方法里的get,set方法,进行数据的设置和获取。

 Object.defineProperty(Vue.prototype, '$data', {
     get () {
      return this._data
     },
     set (newData) {
       if (newData !== this._data) {
         this._setData(newData)
       }
     }   })

从这段源码可以看出设置数据时会调用setData方法,而setData的实现如下

Vue.prototype._setData = function (newData) {
    newData = newData || {}
    var oldData = this._data
    this._data = newData
    var keys, key, i
    // unproxy keys not present in new data
    keys = Object.keys(oldData)
    i = keys.length
    while (i--) {
      key = keys[i]
      if (!(key in newData)) {
        this._unproxy(key)
      }
    }
    // proxy keys not already proxied,
    // and trigger change for changed values
    keys = Object.keys(newData)
    i = keys.length
    while (i--) {
      key = keys[i]
      if (!hasOwn(this, key)) {
        // new property
        this._proxy(key)
      }
    }
    oldData.__ob__.removeVm(this)
    observe(newData, this)
    this._digest()
  }

这段代码的后三行可知首先移除旧的数据,然后调用observe(newData, this);

export function observe (value, vm) {
  if (!value || typeof value !== 'object') {
    return
  }
  var ob
  if (
    hasOwn(value, '__ob__') &&
    value.__ob__ instanceof Observer
  ) {
    ob = value.__ob__
  } else if (
    shouldConvert &&
    (isArray(value) || isPlainObject(value)) &&
    Object.isExtensible(value) &&
    !value._isVue
  ) {
    ob = new Observer(value)
  }
  if (ob && vm) {
    ob.addVm(vm)
  }
  return ob

}
根据新的数据建立一个新的观察对象,这里提一下,vue用的是订阅模式,首先会把每个数据订阅一下,当数据变化时,会通知watcher重新计算值
最后一行代码this._digest()就是通知更新对象的值,把对象设置成newData,我理解的大概过程是这样的,大家看到有错误理解的欢迎给我指出来。这里提醒一下之前犯过的错误,例如:

<template>
  <p>{{user.sex}}</p>
</template>

Data(){
User:{}
}
Ready(){
This.user={name:’smx’,age:12};
This.user.sex=’女’;
}

这将在视图里面无法显示,this.user是通过defineProperty里set方法设置进去的,所以在后面再设置属性的时候对象将不能跟踪到该属性

Logo

前往低代码交流专区

更多推荐