Fuente de datos en respuesta a los principios de la interpretación de

prefacio

Al aprender a entender el Everest principio de la fuente Vue supuesto Responsive.

principio de respuesta

1. El punto central: Object.defineProperty
2. Por defecto Vue durante la inicialización de datos utilizando los datos de atributos se Object.defineProperty redefinir todos los atributos, cuando la página correspondiente al atributo adquirida. Recopilada será dependiente (colector de corriente montaje Vigía) Si la propiedad notificará a la dependencia operación de actualización cambiado.

Lo que es dependiente de la colección?
Por Object.definePropertyel tiempo para re-definir los atributos de datos, interceptar, entonces la representación real; que antes de la serie de proceso de representación real depende de la colección lógica 上边有说,会在依赖收集的时候为每一个属性创建一个watcher,如果属性发生变化,则通知对应的 watcher 更新视图.

Para mirar la fuente
1, el primer constructor inicializa miradas, src/core/instance/index.jsporque compartimos los principios fundamentales de los datos sensibles, es decir, cómo se inicializan los datos Vue render y acumulación de escucha, sobre todo para ver el módulo stateMixin
Aquí Insertar imagen Descripción
2, en el stateMixinmódulo, miramos directamente en la initDatafunción

function initData (vm: Component) { // 初始化data
  let data = vm.$options.data // 获取到用户传入的data数据
  data = vm._data = typeof data === 'function' // 模板语法与标准语法区分获取data数据
    ? getData(data, vm)
    : data || {}
  if (!isPlainObject(data)) { 
    data = {}
    process.env.NODE_ENV !== 'production' && warn(
      'data functions should return an object:\n' +
      'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
      vm
    )
  }
  // proxy data on instance
  const keys = Object.keys(data)
  const props = vm.$options.props
  const methods = vm.$options.methods
  let i = keys.length
  while (i--) {
    const key = keys[i]
    if (process.env.NODE_ENV !== 'production') {
      if (methods && hasOwn(methods, key)) {
        warn(
          `Method "${key}" has already been defined as a data property.`,
          vm
        )
      }
    }
    if (props && hasOwn(props, key)) {
      process.env.NODE_ENV !== 'production' && warn(
        `The data property "${key}" is already declared as a prop. ` +
        `Use prop default value instead.`,
        vm
      )
    } else if (!isReserved(key)) {
      proxy(vm, `_data`, key) // es6 proxy 代理
    }
  }
  /*
  中间我就跳过了,看意思是非生产环境下,对 props , methods 的一些定义,声明做的判断,不允许重复声明
  另外就是添加了 proxy , es6 新增代理属性 , 包含所有 Object.defineProperty 的功能, 重要的一点是解决 	了不能对象监听的问题等。
  */
  // observe data
  observe(data, true /* asRootData */) // 重点在这儿,为每一个data属性创建一个watcher
}

重点 : observe(data, true /* asRootData */) // 重点在这儿,为每一个data属性创建一个wathcer Luego fuimos a la observer 类

3, src/core/observer/index.jslínea 37
está por debajo de la clase de observador, en concreto que se haga, mirada al código

export class Observer {
  value: any;
  dep: Dep;
  vmCount: number; // number of vms that have this object as root $data

  constructor(value: any) { // 构造函数
    this.value = value
    this.dep = new Dep()
    this.vmCount = 0
    def(value, '__ob__', this)
 /*
 观测呢分为两种,一种是数组,一种是对象
 */
    if (Array.isArray(value)) { // 是数组
      if (hasProto) {
        protoAugment(value, arrayMethods) // 改写数组原型方法
      } else {
        copyAugment(value, arrayMethods, arrayKeys) // 复制数组已有方法
      }
      this.observeArray(value) // 深度观察数组中的每一项 , 下边方法
    } else { 
      this.walk(value) // 重新定义对象类型数据   下边方法
    }
  }

  /**
   * Walk through all properties and convert them into
   * getter/setters. This method should only be called when
   * value type is Object.
   */
  walk (obj: Object) {
    const keys = Object.keys(obj)
    for (let i = 0; i < keys.length; i++) { // 遍历对象
      defineReactive(obj, keys[i]);  // 定义响应式数据,这里可以看到 defineReactive 方法
    }
  }

  /**
   * Observe a list of Array items.
   */
  observeArray (items: Array<any>) { // 遍历数组
    for (let i = 0, l = items.length; i < l; i++) {
      observe(items[i])  // 观测数组中的每一项 
    }
  }
}

Por el código de arriba, vemos la cosa más importante que hacer, es distinguir entre las matrices y objetos, y los datos y objetos de recorrido, crear observador watcher=>defineReactive 方法

Llegará en la parte superior cuando se trata de la matriz observeArraymétodo, que consiste en recorrer la llamada observer, algunos tipos de datos y determinar si el monitor no había estado escuchando a la parte posterior devolución de llamada marcha para crear una observación.

src/core/observer/index.js 113 line

export function observe (value: any, asRootData: ?boolean): Observer | void {
  if (!isObject(value) || value instanceof VNode) {
    /* 
    不是对象不进行观测,如:不管是模板语法还是标准语法data均是一个对象
    
    data () {   模板语法返回一个对象
      return  {}
    } 
    new Vue ({  标准语法 data 也是一个对象
      data:{}
    })
    */
    return
  }
  let ob: Observer | void
  if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { // 已经被监听的,不会重复监听
    ob = value.__b__
  } else if (
    shouldObserve &&
    !isServerRendering() &&
    (Array.isArray(value) || isPlainObject(value)) &&
    Object.isExtensible(value) && // 是否可扩展
    !value._isVue
  ) {
    ob = new Observer(value) //重点,重点,重点, 回调回去,观测对象类型
  }
  if (asRootData && ob) {
    ob.vmCount++
  }
  return ob
}

Si no es una matriz, y luego ir directamente al defineReactiveMétodo de
src/core/observer/index.js148 líneas defineReactive 响应式数据绑定关键方法donde utilizamos la palabra que es la aplicación Object.defineProperty (); todos los datos de inicialización vendrán aquí.

export function defineReactive (
  obj: Object,
  key: string,
  val: any,
  customSetter?: ?Function,
  shallow?: boolean
) {
  const dep = new Dep()

  const property = Object.getOwnPropertyDescriptor(obj, key)
  if (property && property.configurable === false) {
    return
  }

  // cater for pre-defined getter/setters
  const getter = property && property.get
  const setter = property && property.set
  if ((!getter || setter) && arguments.length === 2) {
    val = obj[key]
  }

  let childOb = !shallow && observe(val) // 是数组则递归观测
  Object.defineProperty(obj, key, { // 重点
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () { // 数据的取值
      const value = getter ? getter.call(obj) : val
      if (Dep.target) {
        dep.depend()  // 收集依赖 watcher
        if (childOb) {
          childOb.dep.depend()  // 收集依赖
          if (Array.isArray(value)) {
            dependArray(value)
          }
        }
      }
      return value
    },
    set: function reactiveSetter (newVal) { // 数据的设置值
      const value = getter ? getter.call(obj) : val
      /* eslint-disable no-self-compare */
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return
      }
      /* eslint-enable no-self-compare */
      if (process.env.NODE_ENV !== 'production' && customSetter) {
        customSetter()
      }
      // #7981: for accessor properties without setter
      if (getter && !setter) return
      if (setter) {
        setter.call(obj, newVal)
      } else {
        val = newVal
      }
      childOb = !shallow && observe(newVal)
      dep.notify() // 触发数据对应的依赖进行更新 , 重点,重点,往下看
    }
  })
}

Todas las colecciones de observador Dep, que es una colección de wathcer, al crear los datos observados se crea para cada atributo del watcherobservador ( Object.defineProperty方法的 get 里边), entonces la actualización de los datos de disparo setllamadas a métodos dep.notify(), vistazo al código
src/core/observer/dep.js, línea 13, Dep gusta ver a la sierra constructor, complemento vigilante, vigilante de eliminación y así sucesivamente, entonces creo que el punto de vista método de actualizaciónnotify()

export default class Dep {
  static target: ?Watcher;
  id: number;
  subs: Array<Watcher>;

  constructor () {
    this.id = uid++
    this.subs = []
  }

  addSub (sub: Watcher) {
    this.subs.push(sub)
  }

  removeSub (sub: Watcher) {
    remove(this.subs, sub)
  }

  depend () {
    if (Dep.target) {
      Dep.target.addDep(this)
    }
  }

  notify () { // 通知存储的依赖更新
    // stabilize the subscriber list first
    const subs = this.subs.slice()
    if (process.env.NODE_ENV !== 'production' && !config.async) {
      // subs aren't sorted in scheduler if not running async
      // we need to sort them now to make sure they fire in correct
      // order
      subs.sort((a, b) => a.id - b.id)
    }
    for (let i = 0, l = subs.length; i < l; i++) {
      subs[i].update() // 依赖中对应修改属性的update方法
    }
  }
}

update ()Métodos src/core/observer/wachter.js166 filas, de hecho, esta es la definición de wachterla clase observador, dentro de varios de operación wachtermétodos del observador, tales como: añadir, modificar, eliminar similares.

resumen

Pues bien, el análisis aquí, de hecho, ha sido muy claro para los datos sensibles principio, el proceso global es:
Aquí Insertar imagen Descripción

Publicado 21 artículos originales · ganó elogios 40 · vistas 6071

Supongo que te gusta

Origin blog.csdn.net/HiSen_CSDN/article/details/104807792
Recomendado
Clasificación