Análisis de código fuente series-Vue.set / vm.$set
Detallado
Directorio de artículos
Descripción de funciones y conceptos
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.set
Y losvm.$set
mé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.defineProperty
solo 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 $set
mé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 $set
es 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, $set
la 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.defindPropety
no 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.data
puede agregar directamente a los datos - Tenga en cuenta que
ob
se 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$set
devuelve un valor de retorno de la corriente - Si el objeto es nuevo, pasó al
defineReactive$$1
método de línea 1106
Agregar un defineReactive$$1
mé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
get
y elset
método de destino . - 1035 Hay una variable superficial en nuestro código anterior en esta variable no existe,
!shallow
eso es cierto. Por lo tanto, la implementación de unobserve
mé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
observe
análisis anterior , conocemosobserve
esa 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.target
vi como un observador globalwatch
. Entonces, si haydep.target
una llamada a un destino para eldepend
método actual , que es del métodoDep
heredado. Equivale a registrar una devolución de llamada para ver el evento (que se estimawatch
ycomputed
un presagio enterrado) - 1052
set
método de línea de salida . También inicie el suyo propiogetter
para 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 loswatch
métodos adentronewVal
yoldVal
se están registrando en este momento. - Finalmente, se devuelve el valor actual
$set
y 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.target
tiene notas muy detalladas, visor único a nivel mundial
El núcleo es recordar algunos addSub
removeSub
depend
notify
mé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$set
primer 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 Observe
observe 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 objetodefineReactive$$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.defindPropety
los métodosget
yset
, respectivamente, en estos dos métodos para desencadenar el evento correspondiente. -
Debido a JS y las
Object.defindPropety
restricciones que no se pueden agregar dinámicamente, es necesario monitorear la propiedad, por lo que debemos usarVue.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.defindPropety
cambio 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 usarseVue.set
para activar manualmente una actualización, esta vezVue.set
solo 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.$set
Explicación detallada Esta es la nueva dirección del blog, puede echar un vistazo si está interesado