Para comprender el enlace bidireccional de datos de vue2, comprenderá mejor después de escribirlo a mano ~
1. Parte de los datos de la página.
Antes de implementar el enlace bidireccional de datos, primero preparamos los datos que necesitamos usar y luego implementamos la parte del código.
(1) Estructura de la página
Aquí es necesario completar la correlación entre los datos vinculados por el modelo v y el valor en la expresión de interpolación de la estructura de la página, para lograr el efecto del enlace de datos bidireccional de vue.
<body id="app">
<span>up主:{
{ name }}</span>
<input type="text" v-model="name">
<span>更多:{
{ more.like }}</span>
<input type="text" v-model="more.like">
</body>
(2) parte del guión
El archivo vue importado a través de la parte de la etiqueta script no es el vue real , es decir, la parte del código que escribiremos inmediatamente.
En el, almacenamos la identificación en la etiqueta <body/> de la parte html para nuestra conveniencia en el futuro.
<script src="./vue.js"></script>
<script>
const vm = new Vue(
{
el: '#app',
data: {
name: 'kerwin',
more: {
like: '点赞'
}
}
}
)
console.log(vm);
</script>
Dos, código vue.js
(1) Crear una instancia de Vue
Debido a que incluso consideramos que la cantidad de código es relativamente grande y necesitamos usar constructores, elegimos la clase clase para crear constructores .
El objeto pasado cuando obj_instance es una instancia, primero. Primero guardamos su atributo de datos en $data en la instancia , pero también se usa en vue
class Vue {
constructor(obj_instance) {
this.$data = obj_instance.data
}
}
(2) Realizar el secuestro de datos
Punto clave: necesitamos usar Object.defineProperty para lograr el secuestro de datos . Este es el caso en vue2, pero vue3 es ligeramente diferente. No es difícil entender vue3 después de comprender vue2.
1. Cree una función para el secuestro de datos.
Debido a que lo que necesitamos es un enlace bidireccional, son los datos en los datos, por lo que necesitamos pasar datos.
class Vue {
constructor(obj_instance) {
// ....
// 在构造函数中将data 传入
Observer(this.$data)
}
}
// 实现数据劫持
function Observer(data_instance) {
}
2. Atravesar el objeto de datos e implementar el secuestro de datos.
Comprensión: Object.defineProperty
Object.defineProperty(objeto de operación, propiedad de operación, { } )
{ } Pasar el objeto e implementar el monitoreo de datos en el objeto
Este método puede modificar las propiedades existentes en el objeto.
// 数据劫持
function Observer(data_instance) {
// 遍历对象中的每一个属性
Object.keys(data_instance).forEach(key => {
Object.defineProperty(data_instance, key, {
// 设置属性描述符可以改变
configurable: true,
// 设置是否可枚举
enumerable: true,
get() {
},
set(newValue) {
},
})
})
}
3. Configurar definidores y captadores
Podemos comprobar los datos en la consola antes de configurar.
① captador
Generemos vm antes que el observador. Cuando accedemos al valor del atributo en vm, encontramos que los datos no están definidos , porque los obtenemos y no regresamos al acceder , lo que resulta en la pérdida de datos.
Entonces, cuando atravesamos la clave, primero guardamos los datos en la variable de valor. Cuando accedamos a ella, se activará get y se devolverá el valor , para que los datos estén bien.
② colocador
Cuando configuramos los datos en vm, se activará la función set y su parámetro formal (newValue) son los datos que configuramos, por lo que podemos establecer el valor directamente como newValue , y los datos se pueden modificar normalmente en este momento.
// 数据劫持
function Observer(data_instance) {
// 如果没有值或不为对象那么直接返回出去
Object.keys(data_instance).forEach(key => {
++ let value = data_instance[key]
Object.defineProperty(data_instance, key, {
configurable: true,
enumerable: true,
get() {
++ console.log(`访问了${key}属性 --> 属性值为:${value}`);
++ return value // 将原本数据return出来
},
set(newValue) {
++ value = newValue
++ console.log(`修改了${key}属性值${value} --> 为${newValue}`);
},
})
})
}
4. Procese el objeto en el atributo del objeto de datos.
Debido a que también hay objetos en el valor del atributo de datos que configuramos, usamos object.key para atravesar solo la primera capa. Si queremos secuestrar todos los datos en los datos, entonces debemos usar la recursividad .
Cuando recorremos la clave, primero llamamos recursivamente para ver si hay un valor o tipo de datos como objeto, si es así, continuamos recurriendo para resolver este problema.
function Observer(data_instance) {
// 如果没有值或不为对象那么直接返回出去
++ if (!data_instance || typeof data_instance !== 'object') return
Object.keys(data_instance).forEach(key => {
let value = data_instance[key]
// 递归,内部属性
++ Observer(value)
Object.defineProperty(data_instance, key, {
// ....
})
})
}
5. Manejar la asignación de un nuevo objeto a una propiedad.
Cuando reasignamos una propiedad a un objeto, no se repetirá, porque observar ya se ejecutó, por lo que debemos llamar a observar nuevamente en el configurador.
Object.defineProperty(data_instance, key, {
// ...
set(newValue) {
// 递归
++ Observer(newValue)
value = newValue
return console.log(`修改了${key}属性值${value} --> 为${newValue}`);
},
})
Hay demasiados, así que no los explicaré, los agregaré más tarde.
Para más detalles, consulte gitee y clónelo, la dirección es la siguiente