El uso y principio de Vue.set (análisis de series de código fuente)

Análisis de código fuente series-Vue.set / vm.$setDetallado

Descripción de funciones y conceptos

Documento oficial: Vue-set

Agregue una propiedad al objeto receptivo y asegúrese de que esta nueva propiedad también responda y active la actualización de la vista. Debe usarse para agregar nuevas propiedades al objeto reactivo, porque Vue no puede detectar nuevas propiedades ordinarias (como this.myObject.newProperty = 'hi')

Limitaciones No está
permitido agregar dinámicamente atributos de respuesta a nivel de raíz. tal como:

// 错误写法
this.$set(this, 'newkey', 1111)

// 正确写法
this.$set(this.obj, 'newkey', 111)

// 取值: this.obj.newkey => 111

resumen

  • Vue.setY los vm.$setmétodos son en realidad los mismos, pero la redacción no es la misma
  • El efecto es agregar atributos dinámicamente a la página, y los atributos agregados dinámicamente también son atributos sensibles

Por qué usar set para agregar atributos receptivos

Observe el principio de respuesta de vue: el principio de enlace de datos de dos vías de vue
se puede ver de hecho confiar en una respuesta Object.defineProperty
y Object.definePropertysolo escuchar uno de los atributos de un objeto, si hay varias propiedades, es necesario escuchar

Mire una demostración para comprender:

var data = {
    
    }

Object.defineProperty(data, 'data1', {
    
    
  get: function() {
    
    
    console.log('get data1')
    return this.value
  },
  set: function(newVal) {
    
    
    console.log('set data1')
    this.value = newVal
  }
})

data.data1 = 111 // 将会打印 set data1
console.log(data.data1) // 先打印 get data1  然后才是 111

data.data2 = 222 // 无打印,无报错
console.log(data.data2) // 直接打印222。表示没有进过 `Object.defineProperty`

Empiece a mirar el código fuente

Aquí hay una demostración para depurar

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
  var app = new Vue({
     
     
    el: '#app',
    data: {
     
     
      addData: {
     
     }
    }
  })
  debugger
  app.$set(app.addData, 'newkey', 1111)
</script>

El primero en ingresar los $setmétodos de la época, primero llegó a la sección de valor predeterminado, esta vez para devolver un valor nulo, después de la devolución, volver a ingresar $setes la parte que necesitamos depurar

En el modo de depuración, ingrese el método establecido

Línea 2 1081 un método para detectar el tipo de datos del nodo objetivo, es decir, $setla detección del primer parámetro

  • 1085-1089 determinan el tipo de la matriz Después de todo, debido a que el tipo especial Object.defindPropetyno puede detectar el cambio de la matriz, el cambio de la matriz se actualiza manualmente.
  • 1090-1093 es para determinar si el atributo ya existe antes, y no es necesario repetir el monitoreo si existe.
  • 1095-1100 es para determinar que el nodo raíz no se this.datapuede agregar directamente a los datos
  • Tenga en cuenta que obse observa la variable de fila 1094 (observador) para abreviar. También se usa para determinar si la variable ha sido monitoreada
  • Los valores que han sido monitoreados y no necesitan ser monitoreados repetidamente serán devueltos directamente a los correspondientes val. También $setdevuelve un valor de retorno de la corriente
  • Si el objeto es nuevo, pasó al defineReactive$$1método de línea 1106

Agregar un defineReactive$$1método de escucha

  • 1021 initialize new Dep view el análisis de dep look es necesario un análisis de dep . Esto implica muchos de los siguientes procesos. El csdn no admite la navegación hash, por lo que debe deslizarlo manualmente hacia abajo y echar un vistazo ~
  • 1023-1026 Determine si el objeto se puede leer y escribir
  • 1019--1033 obtener el objeto gety el setmétodo de destino .
  • 1035 Hay una variable superficial en nuestro código anterior en esta variable no existe, !shalloweso es cierto. Por lo tanto, la implementación de un observemétodo para ver el análisis de observación csdn no admite la navegación hash, debe deslizarse manualmente hacia abajo para ver ~
  • Después de leer el observeanálisis anterior , conocemos observeesa propiedad para su hijo, el ciclismo agrega la escucha.
  • La línea 1039 está vinculada al evento que obtiene el valor del atributo. Al obtener el valor correspondiente, lo Dep.targetvi como un observador global watch. Entonces, si hay dep.targetuna llamada a un destino para el dependmétodo actual , que es del método Depheredado. Equivale a registrar una devolución de llamada para ver el evento (que se estima watchy computedun presagio enterrado)
  • 1052 setmétodo de línea de salida . También inicie el suyo propio getterpara obtener el valor actual dentro
  • Línea 1069, si estamos copiando un objeto recientemente, él tiene que volver a agregar una retención de datos para estos objetos en un bucle, si ya se ha retenido, se puede omitir, que es el código de arriba.
  • Las últimas 1070 líneas se llaman después de conjunto dep.notify(). Almacena la hora en la que se debe activar la actualización del objeto correspondiente (modo de observador de suscripción). Ahora que el valor se actualiza, se activa a la función de suscripción correspondiente (el reloj también se activa en este momento y la vista también se actualiza en este momento) . Y tenemos que obtener el valor establecido antes del frente, por lo que los watchmétodos adentro newValy oldValse están registrando en este momento.
  • Finalmente, se devuelve el valor actual $sety finaliza la ejecución del método.



análisis dep

El código dep no es muy largo. dep es equivalente a un centro de suscripción

  • En la línea 717, puede ver que cada departamento tiene un ID correspondiente y es auto-creciente
  • La línea 718 se puede considerar como un centro de eventos, y toda la monitorización se almacena aquí.
  • Puede ver que hay varios métodos en el prototipo de dep addSub removeSub depend notify. Todos se utilizan para operar el monitor correspondiente, agregar / eliminar, encontrar la dependencia correspondiente y notificar estos métodos.
  • La línea 725 Dep.targettiene notas muy detalladas, visor único a nivel mundial

El núcleo es recordar algunos addSub removeSub depend notifymétodos. Entonces continúa mirando el código ahora

observar el análisis

Notas especialmente reflexivas

Intente crear una instancia de observador para un valor,
intente crear un valor para la instancia de observador
devuelve el nuevo observador si se observa con éxito,
si se observa con éxito, se devuelve el nuevo visor
o el observador existente si el valor ya tiene uno.
O el observador existente de (si el valor ya contiene uno)

  • Parece que value.__ob__si lo hay, entonces esta propiedad habría sido un observador, y este es nuestro $setprimer paso en un juicio en cuanto a __ob__la

  • Luego distinga la matriz, la matriz no tiene observadores

  • Principalmente para ver la línea 1003, cree un nuevo observador new Observeobserve la capital, no el objeto actual

  • new Observe En la Figura 2 a continuación, no hablaré de ello por separado.

  • 926 líneas. Para __ob__agregar propiedades, no se equivoque y __ob__configúrelo en un tipo no enumerable. Para obtener más detalles, puede ver el código que va en 926

  • 927-933 son todos para operaciones de matriz

  • Línea 935, el método de paseo del objeto actual. Pegando el código directamente, podemos ver que es un bucle, atravesando nuestro objeto una vez y llamándolo para cada objeto defineReactive$$1. Como puede ver, este método solo se llamará si el valor es un tipo de objeto.

  • Dado que se llama defineReactive$$1. Entonces se forma aquí una recursividad, el principio de la recursividad es dejar de llamar cuando el atributo ya no es un objeto defineReactive$$1.

  • Después de ver esto, el siguiente paso debería retroceder para agregar un método para escuchar la línea 1035 de defineReactive $$

/**
 * Walk through all properties and convert them into
 * getter/setters. This method should only be called when
 * value type is Object.
 */
Observer.prototype.walk = function walk(obj) {
    
    
  var keys = Object.keys(obj)
  for (var i = 0; i < keys.length; i++) {
    
    
    defineReactive$$1(obj, keys[i])
  }
}

para resumir

  • El principio de respuesta vue se basa en Object.defindPropetylos métodos gety set, respectivamente, en estos dos métodos para desencadenar el evento correspondiente.

  • Debido a JS y las Object.defindPropetyrestricciones que no se pueden agregar dinámicamente, es necesario monitorear la propiedad, por lo que debemos usar Vue.set()el método

  • Vue.set()El interior del método es un proceso de procesamiento cíclico. Si el nuevo monitor actual es un objeto, continuará llamándose a sí mismo para formar una recursividad hasta que el último atributo secundario sea ​​un 数组/非对象类型parámetro, la recursividad finalice y luego agregará un monitor para usted mismo, en el monitor Desencadenará otros métodos relacionados (se desencadenarán los eventos suscritos en Dep). Forme nuestro enlace de datos bidireccional común

  • Dado que el Object.defindPropetycambio solo puede monitorear el objeto, por lo que el valor de un índice en particular dentro del cambio de matriz no está escuchando, por lo que debe usarse Vue.setpara activar manualmente una actualización, esta vez Vue.setsolo realiza el valor actualizado y no repetirá el monitoreo de Nuevo aumento

Artículo original primero: Analice el código fuente series-Vue.set / vm.$setExplicación detallada Esta es la nueva dirección del blog, puede echar un vistazo si está interesado

Supongo que te gusta

Origin blog.csdn.net/Jioho_chen/article/details/107005845
Recomendado
Clasificación