Notas de estudio de gran front-end: principio del sistema de respuesta Vue.js 3.0

Principio del sistema de respuesta Vue.js 3.0

Fuente de salida del contenido del artículo: gran campo de entrenamiento de alto pago inicial

1. Introducción

1. Revisión receptiva de Vue.js

  • El objeto proxy implementa la supervisión de propiedades
  • Anidación de atributos de varios niveles, procesando el siguiente nivel de atributos en el proceso de acceso a los atributos
  • Las propiedades agregadas dinámicamente se monitorean de forma predeterminada
  • La operación de eliminación del atributo de monitoreo predeterminado
  • Índice de matriz de supervisión predeterminado y propiedad de longitud
  • Se puede utilizar como módulo independiente

2. Funciones básicas

  • eactive / ref / toRefs / calculado
  • efecto
  • pista
  • desencadenar

Dos, revisión del objeto proxy

1. En modo estricto, la función Proxy debe devolver un valor booleano; de lo contrario, informará un TypeError

Uncaught TypeError: 'set' en proxy: trap devuelto falso para la propiedad 'foo'

'use strict'
// 问题1: set和deleteProperty中需要返回布尔类型的值
// 严格模式下,如果返回false的话,会出现TypeError的异常
const target = {
    
    
  foo: 'xxx',
  bar: 'yyy'
}
// Reflect.getPrototypeOf()
// Object.getPrototypeOf()
const proxy = new Proxy(target, {
    
    
  get (target, key, receiver) {
    
    
    // return target[key]
    return Reflect.get(target, key, receiver)
  },
  set (target, key, value, receiver) {
    
    
    // target[key] = value
    return Reflect.set(target, key, value, receiver) // 这里得写return
  },
  deleteProperty(target, key) {
    
    
    // delete target[key]
    return Reflect.deleteProperty(target, key) // 这里得写return
  }
})

proxy.foo = 'zzz'

2. Utilice el receptor en Proxy y Reflect

Receptor en Proxy: Proxy o un objeto
que hereda Proxy Receptor en React: Si el objeto objetivo tiene un getter, este en el getter apunta al receptor

const obj = {
    
    
  get foo () {
    
    
    console.log(this)
    return this.bar
  }
}

const proxy = new Proxy(obj, {
    
    
  get(target, key, receiver) {
    
    
    if (key === 'bar') {
    
    
      return 'value - bar'
    }
    return Reflect.get(target, key, receiver) // 执行this.bar的时候,this指向代理对象,也就是获取target.bar
  }
})
console.log(proxy.foo) // value - bar

Si está return Reflect.get(target, key, receiver)escrito return Reflect.get(target, key), esto en el atributo receptivo foo aún apunta al objeto original obj, this.bar no está definido y, después de que se pasa el receptor, el atributo this en el atributo receptivo apunta al nuevo proxy de objeto receptivo, this.bar Regreso value - bar.

三 、 reactivo

  • Aceptar un parámetro, determinar si este parámetro es un objeto
  • Crear controlador de objetos interceptor, establecer get / set / deleteProperty
  • Devuelve el objeto Proxy

Sé reactivo por ti mismo

function isObject(value) {
    
    
  return value !== null && typeof value === 'object'
}

function convert(target) {
    
    
  return isObject(target) ? reactive(target) : target
}

const hasOwnProperty = Object.prototype.hasOwnProperty

function hasOwn(target, key) {
    
    
  return hasOwnProperty.call(target, key)
}

export function reactive(target) {
    
    
  if (!isObject(target)) return target

  const handler = {
    
    
    get (target, key, receiver) {
    
    
      // 收集依赖
      // track(target, key) // 稍后解注释
      console.log('get', key)
      const ret = Reflect.get(target, key, receiver)
      return convert(ret)
    },
    set (target, key, value, receiver) {
    
    
      const oldValue = Reflect.get(target, key, receiver)
      let ret = true
      if (oldValue !== value) {
    
    
        ret = Reflect.set(target, key, value, receiver)
        // 触发更新
        // trigger(target, key) // 稍后解注释
				console.log('set', key, value)
      }
      return ret
    },
    deleteProperty (target, key) {
    
    
      const hasKey = hasOwn(target, key)
      const ret = Reflect.deleteProperty(target, key)
      if (hasKey && ret) {
    
    
        // 触发更新
        // trigger(target, key) // 稍后解注释
				console.log('detele', key)
      }
      return ret
    }
  }

  return new Proxy(target, handler)
}

utilizar:

<body>
  <script type="module">
    import {
     
      reactive } from './reactivity/index.js'
    const obj = reactive({
     
     
      name: 'zs',
      age: 18
    })
    obj.name = 'lisi'
    delete obj.age
    console.log(obj)
  </script>
</body>

La salida es:

establecer nombre lisi
index.js: 39 detele age
index.html: 17 Proxy {nombre: "lisi"}

Cuarto, recopilar dependencias

Inserte la descripción de la imagen aquí

Cinco, efecto, pista

let activeEffect = null
export function effect(callback) {
    
    
  activeEffect = callback
  callback() // 访问响应式对象的属性,去收集依赖
  activeEffect = null
}

let targetMap = new WeakMap()
export function track(target, key) {
    
     // 收集依赖
  if (!activeEffect)return
  let depsMap = targetMap.get(target)
  if(!depsMap) {
    
    
    targetMap.set(target, depsMap = new Map())
  }
  let dep = depsMap.get(key)
  if(!dep) {
    
    
    depsMap.set(key, dep = new Set())
  }
  dep.add(activeEffect)
}

Seis, gatillo

export function trigger(target, key) {
    
     // 触发依赖
  const depsMap = targetMap.get(target)
  if(!depsMap)return
  const dept = depsMap.get(key)
  if(dept) {
    
    
    dept.forEach(effect => {
    
    
      effect()
    })
  }
}

utilizar:

<body>
  <script type="module">
    import {
     
      reactive, effect } from './reactivity/index.js'
    const product = reactive({
     
     
      name: 'iPhone',
      price: 5000,
      count: 3
    })
    let total = 0
    effect(() => {
     
     
      total = product.price * product.count
    })
    console.log(total) // 15000

    product.price = 4000
    console.log(total) // 12000

    product.count = 1
    console.log(total) // 4000
  </script>
</body>

Siete, ref

eactive vs ref

  • ref puede convertir tipos de datos básicos en objetos sensibles

  • El objeto devuelto por ref también responde a la reasignación a un objeto

  • Objeto devuelto por reactivo, la reasignación pierde reactivo

  • El objeto devuelto por reactivo no se puede deconstruir

  • reactivo

    const product = reactive({
          
          
      name: 'iPhone',
      price: 5000,
      count: 3
    })
    
  • árbitro

    const price = ref(5000)
    const count = ref(3)
    

Implementar ref:

export function ref(raw) {
    
    
  // 判断raw是否是ref创建的对象,如果是的话直接返回
  if (isObject(raw) && raw.__v_isRef)return

  let value = convert(raw)
  const r = {
    
    
    __v_isRef: true,
    get value () {
    
    
      track(r, 'value')
      return value
    },
    set value (newValue) {
    
    
      if(newValue !== value) {
    
    
        raw = newValue
        value = convert(raw)
        trigger(r, 'value')
      }
    }
  }
  return r
}

utilizar:

<body>
  <script type="module">
    import {
     
      reactive, effect, ref } from './reactivity/index.js'
    const price = ref(5000)
    const count = ref(3)
    let total = 0
    effect(() => {
     
     
      total = price.value * count.value
    })
    console.log(total) // 15000

    price.value = 4000
    console.log(total) // 12000

    count.value = 1
    console.log(total) // 4000
  </script>
</body>

Ocho, toRefs

export function toRefs(proxy) {
    
    
  const ret = proxy instanceof Array ? new Array(proxy.length) : {
    
    }
  for (const key in proxy) {
    
    
    ret[key] = toProxyRef(proxy, key)
  }
  return ret
}

function toProxyRef(proxy, key) {
    
    
  const r = {
    
    
    __v_isRef: true,
    get value () {
    
    
      return proxy[key]
    },
    set value (newValue) {
    
    
      proxy[key] = newValue
    }
  }
  return r
}

utilizar

<body>
  <script type="module">
    import {
     
      reactive, effect, toRefs } from './reactivity/index.js'
    function useProduct() {
     
     
      const product = reactive({
     
     
        name: 'iPhone',
        price: 5000,
        count: 3
      })
      return toRefs(product) // 直接返回解构的product不是响应式对象,所以调用toRefs将reactive对象的每个属性都转化成ref对象
    }

    const {
     
      price, count } = useProduct()

    let total = 0
    effect(() => {
     
     
      total = price.value * count.value
    })
    console.log(total) // 15000

    price.value = 4000
    console.log(total) // 12000

    count.value = 1
    console.log(total) // 4000
  </script>
</body>

Nueve, calculado

export function computed(getter) {
    
    
  const result = ref()
  effect(() => (result.value = getter()))
  return result
}

utilizar

<body>
  <script type="module">
    import {
     
      reactive, effect, computed } from './reactivity/index.js'
    const product = reactive({
     
     
      name: 'iPhone',
      price: 5000,
      count: 3
    })
    let total = computed(() => {
     
     
      return product.price * product.count
    })
    console.log(total.value) // 15000

    product.price = 4000
    console.log(total.value) // 12000

    product.count = 1
    console.log(total.value) // 4000
  </script>
</body>

Nota: Trigger / track / effct es la función subyacente, generalmente no se usa. Usar calculado en lugar de efecto

Supongo que te gusta

Origin blog.csdn.net/jal517486222/article/details/108689672
Recomendado
Clasificación