imagen
imagen.png

prefacio

vue3Ha estado en el centro de atención durante dos años desde su lanzamiento, y ahora tiene el impulso para compartir el mundo con reaccionar. Sabemos que se basa en la capacidad del proxy para lograr la capacidad de respuesta, lo que ha resuelto algunos vue2de los problemas restantes. al mismo tiempo, debido a las características del proxy, también ha mejorado el rendimiento del tiempo de ejecución

Todo tiene ventajas y desventajas, proxyaunque es invencible, también tiene sus propias limitaciones, lo que lleva a algunas desventajas en mi opinión (de hecho, no se ajusta al método de escritura natural del lenguaje js, algunas personas piensan que es un especial método de escritura, y él no pertenece a las desventajas)

  • 1. La implementación del sistema responsivo de valores primitivos da como resultado que se debe empaquetar como un objeto y acceder .valuepor medio de
  • 2. La desestructuración de ES6 no se puede utilizar a voluntad. rompería su naturaleza receptiva

Impulsado por la curiosidad, investigué y medité por qué causaba estos dos inconvenientes.

Implementación de un sistema reactivo para valores primitivos

Antes de comprender la implementación de un sistema receptivo de valores primitivos, ¡revisemos primero las capacidades del proxy!

const obj = {
  name'win'
}

const handler = {
  getfunction(target, key){
    console.log('get--', key)
    return Reflect.get(...arguments)  
  },
  setfunction(target, key, value){
    console.log('set--', key, '=', value)
    return Reflect.set(...arguments)
  }
}

const data = new Proxy(obj, handler)
data.name = 'ten'
console.log(data.name,'data.name22')

复制代码

En el código anterior, encontramos que el uso del proxy en sí mismo es la intercepción del objeto new Proxy, y el objeto obj se intercepta a través del valor de retorno de

De esta manera, cuando acceda al valor en el objeto, disparará el getmétodo , y cuando modifique el valor en el objeto, disparará el setmétodo .

Pero cuando se trata del valor original, no tiene ningún objeto, ¿qué debo hacer? No se new proxypuede usar.

Desesperados, solo podemos envolverlo, por lo que tenemos .valueacceso para usar

Echemos un vistazo a la implementación específica.

import { reactive } from "./reactive";
import { trackEffects, triggerEffects } from './effect'

export const isObject = (value) => {
    return typeof value === 'object' && value !== null
}

// 将对象转化为响应式的
function toReactive(value{
    return isObject(value) ? reactive(value) : value
}

class RefImpl {
    public _value;
    public dep = new Set// 依赖收集
    public __v_isRef = true// 是ref的标识
    // rawValue 传递进来的值
    constructor(public rawValue, public _shallow) {
        // 1、判断如果是对象 使用reactive将对象转为响应式的
        // 浅ref不需要再次代理
        this._value = _shallow ? rawValue : toReactive(rawValue);
    }
    get value() {
        // 取值的时候依赖收集
        trackEffects(this.dep)
        return this._value;
    }
    set value(newVal) {
        if (newVal !== this.rawValue) {
            // 2、set的值不等于初始值 判断新值是否是对象 进行赋值
            this._value = this._shallow ? newVal : toReactive(newVal);
            // 赋值完 将初始值变为本次的
            this.rawValue = newVal
            triggerEffects(this.dep)
        }
    }
}

复制代码

El código anterior es el paquete del valor original. Se empaqueta como un objeto y se accede al valor original a través de los métodos get valuey , lo que da como resultado la operación necesaria, que en realidad es una elección inútil.set value.value

相当于两瓶毒药,你得选一瓶No puedes tener pez y pata de oso

Por qué la desestructuración de ES6 y no poder usarlo destruirá sus funciones de respuesta

La primera pregunta finalmente se entendió, así que echemos un vistazo a la segunda pregunta más importante,为什么结构赋值,会破坏响应式特性

fondo proxy

Antes de comenzar, analicemos por qué el cambio响应式方案

Vue2 se basa en Object.defineProperty   , pero tiene muchos defectos, como la  incapacidad de monitorear la modificación de la matriz en función de los subíndices, y los defectos como Map, Set, WeakMap y WeakSet no son compatibles  .

De hecho, estos no retrasan nuestro desarrollo, vue2 sigue siendo la corriente principal,

Mi entendimiento es 与时俱进que 新一代的版本,一定要紧跟语言的特性,一定要符合新时代的书写风格, aunque proxyhay muchas mejoras en comparación con Object.defineProperty, no está exento de deficiencias. Por ejemplo,不兼容IE

¿Cómo puede haber algo perfecto en el mundo?

¡Tu gran coraje está en renunciar a un poco del presente para construir un futuro!

Principio de implementación

Después de comprender los antecedentes, repasemos el principio en modo falso proxy, aunque todo esto está podrido.

Sin embargo, al escribir hidrología, ¿a qué debe prestar atención? Dos palabras: coherencia.

imagen
imagen.png
        const obj = {
            count1
        };
        const proxy = new Proxy(obj, {
            get(target, key, receiver) {
                console.log("这里是get");
                return Reflect.get(target, key, receiver);
            },
            set(target, key, value, receiver) {
                console.log("这里是set");
                return Reflect.set(target, key, value, receiver);
            }
        });
        
        console.log(proxy)
        console.log(proxy.count)
复制代码

El código anterior es la forma específica de usar Proxy. A través de la cooperación con Reflect, se puede realizar la intercepción de objetos.

imagen
imagen.png

Con tal dependencia, puede lograr la capacidad de respuesta Puede encontrar que todo el objeto de este obj es interceptado, pero encuentra que el objeto está anidado un nivel más profundo.

por ejemplo:


    const obj = {
            count1,
            b: {
                c2
            }
        };
        
        
     console.log(proxy.b)
     console.log(proxy.b.c)
复制代码

No puede interceptar, tenemos que empacar

    const obj = {
            a: {
                count1
            }
        };
        
        function reactive(obj{
            return new Proxy(obj, {
                get(target, key, receiver) {
                    console.log("这里是get");
                    // 判断如果是个对象在包装一次,实现深层嵌套的响应式
                    if (typeof target[key] === "object") {
                        return reactive(target[key]);
                    };
                    return Reflect.get(target, key, receiver);
                },
                set(target, key, value, receiver) {
                    console.log("这里是set");
                    return Reflect.set(target, key, value, receiver);
                }
            });
        };
        const proxy = reactive(obj);
复制代码

Bueno, el principio está hecho, estudiémoslo formalmente.

Ahora, para enumerar algunas situaciones en las que se pierde la capacidad de respuesta que yo sepa:

  • 1. Deconstruir el  props objeto porque pierde su capacidad de respuesta.
  • 2. Asignación directa reactivede objetos reactivos
  • 3. vuexAsignación de API de combinación intermedia

Destrucción  props de objetos porque pierde capacidad de respuesta.

       const obj = {
            a: {
                count1
            },
            b1
        };
            
            //reactive 是上文中的reactive
           const proxy = reactive(obj);
        const {
            a,
            b
        } = proxy;
        console.log(a)
        console.log(b)
        console.log(a.count)
        
复制代码
imagen
imagen.png

En el código anterior, encontramos que la asignación de desestructuración, b 不会触发响应式, a如果你访问的时候, activará la respuesta

¿Por qué es esto?

No te preocupes, ¿vamos a explicar uno por uno?

Analicemos primero por qué la desestructuración de la asignación perderá la capacidad de respuesta.

Sabemos desestructurar la asignación, distinguiendo entre asignación de tipos primitivos y asignación de tipos de referencia,

原始类型的赋值相当于按值传递,引用类型的值就相当于按引用传递

es equivalente a

   // 假设a是个响应式对象
  const a={ b:1}
  // c 此时就是一个值跟当前的a 已经不沾边了
  const c=a.b

// 你直接访问c就相当于直接访问这个值 也就绕过了 a 对象的get ,也就像原文中说的失去响应式
复制代码

Entonces, ¿por qué aresponde?

Debido a que aes un tipo de referencia, recordamos un juicio en el código anterior. Si es un objectentonces reempaquetar como reactivo

Formalmente debido a la característica actual, si es un tipo de referencia, no perderá capacidad de respuesta cuando acceda a su contenido

  // 假设a是个响应式对象
 const a={ b:{c:3}}
 // 当你访问a.b的时候就已经重新初始化响应式了,此时的c就已经是个代理的对象
 const c=a.b

// 你直接访问c就相当于访问一个响应式对象,所以并不会失去响应式
复制代码

Lo anterior explica aproximadamente por qué la asignación de desestructuración puede perder la capacidad de respuesta. Supongo que el documento es demasiado perezoso para explicar el motivo, ¡así que simplemente establecí una regla, tú!

¡No lo use, guarde los errores que crea que son vueciertos y cambie los hábitos de uso del usuario por adelantado! no acostumbro a

Asignación directa reactivede objetos reactivos

Cuando usamos vue3 por primera vez, especificamos que el siguiente código se escribiría

 const vue = reactive({ a1 })
 vue = { b2 }

复制代码

Y luego hacer preguntas reactive, ¿no es receptivo? ¿Por qué después de que asigné el valor, su capacidad de respuesta desapareció y luego gritó, basura vue

De hecho, esto se debe a que no tienes claro el concepto de js native, de hecho, 尤大has hecho los mayores esfuerzos para evitar que cometas errores.

Por ejemplo, debido al problema de la asignación de desestructuración, prohíbe directamente la asignación de desestructuración reactiva.

imagen
imagen.png

Cuando utiliza la operación de asignación de desestructuración, deshabilita directamente

Entonces alguien volvió a preguntar, 为啥props 不给禁用了呢?

因为你的props 的数据可能不是响应式的啊,不是响应式的,我得能啊, especialmente no puede interferir con el uso de la nueva sintaxis por parte del usuario.

Así que es la misma oración: 框架现在的呈现,其实充满了取舍¡A veces son realmente dos botellas de veneno, elige una!

Volviendo al tema, hablemos de la sintaxis js nativa

¡Lo primero que debe confirmar es que la asignación del tipo de referencia de js nativo en realidad se basa en la dirección de referencia!

 // 当reactive 之后返回一个代理对象的地址被vue 存起来,
 // 用一个不恰当的比喻来说,就是这个地址具备响应式的能力
 const vue = reactive({ a1 })
 
 //  而当你对于vue重新赋值的时候不是将新的对象赋值给那个地址,而是将vue 换了个新地址
 // 而此时新地址不具备响应式,可不就失去响应式了吗
 vue = { b2 }

复制代码

Lo anterior es reactivela explicación de la pérdida de capacidad de respuesta, por lo que esta es también la razón por la que muchos usuarios maldicen.不符合他的使用习惯了,这都是被vue2 培养起来的一代

Aquí quiero decir una palabra justa para ti Da 人家又没收你钱,还因为他,你有口饭吃,

Tú mismo no puedes seguir el ritmo de los tiempos y abrazar cosas nuevas, ese eres tú 能耐,

esto es tipico端起碗吃肉,放下筷子骂娘

vuexAsignación de API de composición media

El uso de la asignación en vuex también puede perder capacidad de respuesta


import { computed } from 'vue'
import { useStore } from 'vuex'

export default {
  setup () {
    const store = useStore()
    return {
      // 在 computed 函数中访问 state
      count: computed(() => store.state.count),

      // 在 computed 函数中访问 getter
      double: computed(() => store.getters.double)
    }
  }
}

复制代码

En el código anterior, encontramos que store.getters.doubledebe estar computedenvuelto con . De hecho, la razón es la misma, y ​​también es la razón para la asignación de variables. ¡No las repetiremos aquí!

Al final

Este artículo es, en el proceso de usar vue3, un poco de experiencia y exploración después de la minería, espero que te sea útil, ¡para que puedas obtener una promoción y un aumento salarial en el trabajo!

Finalmente, al final, promoveré mi análisis del código fuente de vue. El análisis puede no ser muy bueno, pero se lee línea por línea. Tal vez puedas pensar en una oración o una oración después de leerla, ¡lo cual es útil!

Dirección de análisis de código fuente [1]

estrella de bienvenida

Acerca de este artículo

Autor: Lao Ji agricultor

https://juejin.cn/post/7114596904926740493

El fin

Si encuentra este contenido inspirador, me gustaría pedirle que me haga tres pequeños favores:
1. Haga clic  en "Mirando" para que más personas vean este contenido
2. Siga el sitio web oficial  https://muyiy.cn , seamos una relación a largo plazo
3. Preste atención a la cuenta oficial "Advanced Front-end Advanced" y responda  a "Add Group" en el fondo de la cuenta oficial  , únase a nosotros para aprender y enviarle preguntas de entrevistas avanzadas bien organizadas.

》》El banco de preguntas que están usando los entrevistadores, ven y mira《


¡No olvides darle me gusta al final!imagen

¡Buena suerte en 2022! ¡Belleza violenta! Violentamente delgado!