Cómo implementa Vue un sistema responsivo
Recientemente, estudié algunos códigos fuente de Vue para implementar sistemas responsivos. Me gustaría registrar algunos de mis logros y pensamientos, con la esperanza de ser útiles para las personas que leen este artículo. Si tiene alguna pregunta, indíquela y trabajaremos juntos.
¿Qué es un sistema responsivo?
En una frase: los cambios de datos impulsan las actualizaciones de las vistas. Esto nos permite escribir código con una mentalidad "basada en datos", centrándonos más en el negocio que en liderar las operaciones. De hecho, la implementación reactiva de Vue es un proceso de seguimiento de cambios y aplicación de cambios.
Principio de capacidad de respuesta de Vue
En el método de secuestro de datos, los cambios de datos serán interceptados en el método de recopilación de dependencias y se activarán las actualizaciones de vista. Utilice es5 Object.defineProperty para interceptar los establecedores y captadores de datos; los captadores recopilan dependencias, los configuradores activan actualizaciones de dependencia y la representación de componentes también se convertirá en una devolución de llamada del observador y se agregará a las dependencias de datos correspondientes.
Publicar-Suscribir
Se implementa utilizando el patrón de diseño de publicación-suscripción. Observer actúa como editor y Watcher actúa como suscriptor. No hay interacción directa entre los dos y unificado. La programación se realiza a través del Dep.
El observador es responsable de interceptar get y set; get activa el Dep para agregar dependencias y establece los horarios del Dep para publicar; agregar Watcher activa la suscripción para obtener datos y agregarlos a la cola de suscriptores del centro de despacho del Dep.
El siguiente diagrama de clases UML muestra las clases que implementan la funcionalidad reactiva en Vue y las referencias entre ellas.
Solo se incluyen algunos métodos de atributos
Las clases en la imagen de arriba se han identificado muy claramente, pero aún se necesita un diagrama de relación de llamada para que el proceso de llamada sea más claro, como se muestra en la siguiente figura.
En respuesta al objeto de datos, cada función get/set de secuestro de clave cierra la instancia de despacho del departamento. Este diagrama muestra el flujo de datos durante los cambios de clave.
Parte del código fuente
El modelo de suscripción/publicación durante los cambios de datos se muestra claramente en la figura anterior. De la figura ya sabemos que podemos suscribirnos a datos específicos agregando. Los observadores cambian.
Entonces, si simplemente nos suscribimos al renderizado del componente como observador, entonces se realizará el renderizado de la vista basada en datos y eso es exactamente lo que hace Vue.
El siguiente fragmento de código proviene de la función Vue.prototype._mount
callHook(vm, 'beforeMount')
vm._watcher = new Watcher(vm , () => {
vm._update( vm._render(), hidratante)
}, noop)
hidratante = false
// Monta manualmente la instancia, llamando a mount sobre sí mismo
//El montaje se llamará en el gancho que inserta para el subcomponente creado para renderizar
if (vm. $ vnode == null) {
vm._isMounted = true
callHook(vm, 'montado')
}
Algunos necesita preguntas para pensar
A #persona se le asigna un nuevo objeto, ¿las propiedades del nuevo objeto también responden?
var vm = new Vue({
el: '#app',
datos: () => ({
persona: null
})
})
vm.person = {nombre: 'zs'}
setTimeout(() => {
// Cambiar nombre
vm.person.name = 'finalmente zs'
}, 3000)
Respuesta : responde.
Razón: Porque cuando Vue secuestra la colección, vuelve a observar el valor, el código fuente es el siguiente.
función reactiveSetter (newVal) {
/* ...omitir parte del código*/
// Aquí observará nuevamente el nuevo valor
p>
childOb = observe(newVal)
dep.notify()
}
# Cuando escuchamos multi propiedades de nivel y se produce la referencia de nivel superior. ¿Se activará una devolución de llamada cuando haya un cambio?
var vm = new Vue({
datos: () => ({
persona: {nombre: 'zorro cebolla'}
}),
ver: {
'persona.nombre'(val) {
consola.log('nombre actualizado', val)
}
}
}
})
vm.persona = {}
Respuesta: Will.
Razón: cuando person.name se pasa a Watcher como expresión, se analizará en la siguiente función
() => {this.vm.person.name}
Esto activará la obtención de la persona primero y luego la obtención del nombre, por lo que la función de devolución de llamada que configuramos no solo se agregará a la dependencia del nombre, sino también a la dependencia de la persona.
#Siguiendo con la pregunta anterior, si se asigna un nuevo objeto a una persona, ¿cómo se recolectará la basura del objeto antiguo y sus dependencias?
Reciclaje del objeto antiguo: dado que la única referencia directa al objeto antiguo es la persona en la instancia de vue, la persona cambiará a la nueva referencia para que el objeto antiguo ya no tenga una referencia y se recicle.
Las dependencias del objeto antiguo todavía existen en las dependencias del observador, sin embargo, cuando se ejecuta la ejecución, se llamará a get() del observador para obtener el valor actual y se ejecutará en get; Recopilación de relaciones y eliminación de dependencias antiguas una vez completada la recopilación.
El código fuente específico es el siguiente:
/**
* Evalúe el captador y recopile las dependencias. profundo) {
atravesar(valor)
}
popTarget()
this.cleanupDeps()
valor de retorno
}
# Cuando sincronizamos los cambios de nombre varias veces, ¿se activará la función de devolución de llamada varias veces?
var vm = new Vue({
datos: () => ({
persona: {nombre: 'zorro cebolla'}
}),
ver: {
'persona.nombre': (val) {
consola.log('nombre actualizado: ' + val)
}
}
})
vm.persona = {nombre: 'zs'}
vm.person.name = 'invincible'
Respuesta: No, porque la ejecución de la función de devolución de llamada de monitoreo es asíncrona y está deduplicada. Puede forzar que se ejecute sincrónicamente mediante sincronización para que se ejecute 2 veces.
Implemente el sistema responsivo usted mismo
Solo incluye funciones principales; consulte aquí el código fuente específico.vuejs.org/v2/guide/reactivity.html.