Vue3: primera introducción a Vue3, creación de proyecto Vue3, API combinada de vue3 (configuración, función de referencia, función reactiva), principio reactivo, propiedades calculadas, propiedades de monitoreo

Ver 3 (1)

1. Introducción a Vue3

El 18 de septiembre de 2020, Vue.js lanzó la versión 3.0, nombre en clave: One Piece (One Piece)

Fueron necesarios más de dos años, más de 2600 presentaciones, más de 30 RFC, más de 600 RP y 99 contribuyentes.

Qué trae Vue3:

1. Mejora del rendimiento

  • Tamaño del paquete reducido en un 42%
  • Bloque de renderizado inicial 55%, bloque de renderizado actualizado 133%
  • Memoria reducida en un 54%

2. Actualización del código fuente

  • Utilice Proxy en lugar de defineProperty para implementar la capacidad de respuesta
  • Reescribiendo la implementación de DOM virtual y Tree-Sgaking

3. Adopte TypeScript

  • Vue3 puede soportar mejor TypeScript

4. Nuevas funciones

(1)API de composición (API de composición)

  • configuración de instalación
  • ref y reactivo
  • reloj 与 reloj Efecto
  • proporcionar e inyectar

(2) Nuevos componentes integrados

  • Fragmento
  • Teletransportarse
  • Suspenso

(3) Otros cambios

  • Nuevos ganchos de ciclo de vida
  • La opción de datos siempre debe declararse como una función.
  • Eliminar la compatibilidad con keyCode como modificador para v-on

2. Crear proyecto Vue3.0

1. Crear usando vue-cli

Documentación oficial: https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create

// 查看@vue/cli版本,确保@vue/cli版本在4.5.0以上
vue --version
// 安装或者升级你的@vue/cli
npm install -g @vue/cli
// 创建
vue create vue_test
// 启动
cd vue_test
npm run serve

2. Crea usando vite

Documento oficial: https://v3.cn.vuejs.org/guide/installation.html#vite
sitio web oficial de vite: https://vitejs.cn

  • ¿Qué es una vit? ——Una nueva generación de herramientas de construcción front-end

  • Las ventajas son las siguientes:

    1. En el entorno de desarrollo, no se requiere operación de empaquetado y es posible un inicio rápido en frío.

    2. Recarga en caliente (HMR) ligera y rápida

    3. Verdadera compilación bajo demanda, sin esperar a que se compile toda la aplicación.

// 创建工程
npm init vite-app <project-name>
// 进入工程目录
cd <project-name>
// 安装依赖
npm install
// 运行
npm run dev

3. API de composición de uso común (API combinada)

1. La configuración que da inicio

En el pasado, solíamos combinar varios elementos de configuración en vue2 (API opcional: datos, método, etc.) En vue3, cambiamos a un nuevo método, es decir, API de composición (API combinada) , y la configuración es una combinación Es la etapa para el rendimiento de la API, y todos los datos y métodos del componente se escriben en la función de configuración.

Esta función de configuración en realidad tiene dos valores de retorno:

  1. devolver un objeto

  2. Devuelve una función de renderizado

El método más utilizado es devolver un objeto y devolver todas las propiedades y métodos utilizados para facilitar su uso en plantillas (por supuesto, ahora existe el azúcar de sintaxis de configuración, que se analizará más adelante)

<template>
  <h1>个人信息</h1>
  <h2>姓名:{
   
   { name }}</h2>
  <h2>年龄:{
   
   { age }}</h2>
  <button @click="sayHello">打招呼</button>
</template>

<script>
import {
      
       h } from "vue";
export default {
      
      
  name: "App",
  // 此处只是测试一下setup,暂时不考虑响应式的问题
  setup() {
      
      
    // 数据
    let name = "potato";
    let age = 18;

    // 方法
    function sayHello() {
      
      
      alert(`我叫${ 
        name},我${ 
        age}岁了`);
    }
      
    // 返回一个对象
    return {
      
      
      name,
      age,
      sayHello,
    };

    // 返回一个渲染函数
    // return () => {return h('h1','哈哈哈哈')};
  },
};
</script>

Nota: No mezcle la configuración con la API opcional en vue2, porque no se puede acceder a los métodos de atributo en vue2 en la configuración ( pero 2 puede acceder a 3 ). Si se mezclan, la configuración con el mismo nombre tendrá prioridad.

Además, no agregue async antes de la configuración, porque el valor de retorno se convertirá en una promesa, no en las propiedades y métodos que devolvemos.

2. función de referencia

¿Recuerdas el atributo ref de vue2? La referencia de vue2 es similar a id. Revisar el atributo ref de Vue2

La referencia de Vue3 es una función.

Función: Definir datos responsivos.

Ejemplo: Haga clic en el botón para modificar la información

<template>
  <h1>个人信息</h1>
  <h2>姓名:{
   
   { name }}</h2>
  <h2>年龄:{
   
   { age }}</h2>
  <button @click="changeInfo">修改信息</button>
</template>

<script>
import {
      
       ref } from "vue";
export default {
      
      
  name: "App",
  setup() {
      
      
    // 数据
    let name = ref("potato");
    let age = ref(18);

    // 方法
    function changeInfo() {
      
      
      // 直接这样写的话是不行的,因为ref把数据包装成了对象,对其操作时要加上‘.value’
      // name= "李四";
      // age= 13;
      // console.log(name, age);
      name.value = "李四";
      age.value = 13;
    }

    // 返回一个对象
    return {
      
      
      name,
      age,
      changeInfo,
    };
  },
};
</script>

const xxx = ref(initValue)Creó un objeto de referencia ( objeto RefImp ) que contiene datos receptivos.
Manipule los datos en js: count.value
lea los datos en la plantilla: <div> { {count}} </div>(el atributo de valor se leerá automáticamente aquí)

Por favor agregue la descripción de la imagen.

De hecho, los datos que ref puede aceptar no son solo tipos de datos básicos, sino también tipos de datos complejos, pero es más problemático y requiere.value

<template>
  <h1>个人信息</h1>
  <h3>职业:{
   
   { job.type }}</h3>
  <h3>工作地点:{
   
   { job.address }}</h3>
  <button @click="changeInfo">修改信息</button>
</template>

<script>
import {
      
       ref } from "vue";
export default {
      
      
  name: "App",
  setup() {
      
      
    // 数据
    let job = ref({
      
      
      type: "前端工程师",
      address: "广州",
    });

    // 方法
    function changeInfo() {
      
      ;
      job.value.type = "后端工程师";
      job.value.address = "深圳";
    }

    // 返回一个对象
    return {
      
      
      job,
      changeInfo,
    };
  },
};
</script>

Los tipos de datos básicos y los tipos de datos de objetos implementan la capacidad de respuesta de diferentes maneras: el primero sigue siendo el mismo Object.defineProperty()的get与set, mientras que el segundo depende de reactivefunciones internas.

3. función reactiva

Función: definir datos receptivos de un tipo de objeto (no use reactivo para tipos básicos, use ref)

<script>
import {
    
     ref, reactive } from "vue";
export default {
    
    
  name: "App",
  setup() {
    
    
    // 数据
    let job = reactive({
    
    
      type: "前端工程师",
      address: "广州",
    });
    // 数组也可以
    let hobby = reactive(["吃饭", "睡觉", "打豆豆"]);

    // 方法
    function changeInfo() {
    
    
      job.type = "后端工程师";
      job.address = "深圳";
      hobby[2] = "学习";
    }

    // 返回一个对象
    return {
    
    
      job,
      changeInfo,
      hobby,
    };
  },
};
</script>

const 代理对象 = reactive(源对象)Recibe un objeto o matriz y devuelve un objeto proxy (objeto proxy)

  • Los datos receptivos definidos por reactivo son "profundos"
  • La implementación interna del Proxy se basa en ES6 y los datos internos del objeto fuente se operan a través del objeto proxy.

Cabe señalar aquí que la capacidad de respuesta solo se puede lograr cambiando un determinado atributo en el trabajo. Si cambia el trabajo directamente, se le informará una advertencia que el trabajo es de solo lectura. Si desea cambiar el trabajo, necesita Object.assign(job, newObj) o job= {...job,...newProperties};

4. Principio responsivo en Vue3

(1) Principio de respuesta en Vue2

Antes de comprender el principio de capacidad de respuesta de Vue3, revisemos primero la capacidad de respuesta de Vue2.

Sabemos que vue2 monitorea datos secuestrando Object.defineProperty()datos de tipo de objeto y agregando getter y setterPara las matrices, el método de actualización de la matriz se anula. Revise los principios de monitoreo de datos de vue2

Hay dos problemas con los datos de monitoreo de vue2:

  1. Si agrega o elimina atributos directamente, la interfaz no se actualizará.
  2. Si modifica la matriz directamente mediante subíndices, la interfaz no se actualizará automáticamente.

Estos dos problemas se pueden resolver mediante $set, $delete,splice(数组变更方法)

(2) Proxy en Vue3

En vue3, se resuelven dos problemas en vue2.

<button @click="addSex">添加一个sex属性</button>
<button @click="deleteName">删除一个name属性</button>
    function addSex() {
    
    
      // 如果是vue2,要这样写this.$set(this.person, 'sex', '女');
      person.sex = "女";
    }
    function deleteName() {
    
    
      // 如果是vue2,要这样写this.$delete(this.person, 'name');
      delete person.name;
    }

El siguiente es el principio de simulación de la capacidad de respuesta en vue3:

<script>
  let person = {
    
    
    name: "potato",
    age: 18,
  };
  // 模拟Vue3实现响应式
  const p = new Proxy(person, {
    
    
    // 有人在读取p的某个属性时调用
    get(target, propName) {
    
    
      console.log(`有人读取了p身上的${
      
      propName}属性`);
      return target[propName];
    },
    // 有人在修改p的某个属性、或给p追加某个属性时调用
    set(target, propName, value) {
    
    
      console.log(`有人修改了p身上的${
      
      propName}属性,我要去更新界面了`);
      target[propName] = value;
    },
    // 有人在删除p的某个属性时调用
    deleteProperty(target, propName) {
    
    
      console.log(`有人删除了p身上的${
      
      propName}属性,我要去更新界面了`);
      return delete target[propName];
    },
  });
</script>

Por favor agregue la descripción de la imagen.

Es más riguroso y se Reflect(反射)utiliza para agregar, eliminar, modificar y verificar. Este también es el enfoque del marco. De hecho, no hay mucha diferencia en esencia. Es solo que Reflectpuede capturar mejor los errores y evitar algunos informes de errores, de lo contrario try-catchhabrá que capturarlo. No se enrede demasiado aquí, en realidad es solo para hacer que el marco sea más amigable (menos informes de errores)

  • Proxy(代理)+Reflect(反射)
<script>
  let person = {
    
    
    name: "potato",
    age: 18,
  };
  // 模拟Vue3实现响应式
  const p = new Proxy(person, {
    
    
    // 有人在读取p的某个属性时调用
    get(target, propName) {
    
    
      console.log(`有人读取了p身上的${
      
      propName}属性`);
      return Reflect.get(target, propName);
    },
    // 有人在修改p的某个属性、或给p追加某个属性时调用
    set(target, propName, value) {
    
    
      console.log(`有人修改了p身上的${
      
      propName}属性,我要去更新界面了`);
      Reflate.set(target, propName, value);
    },
    // 有人在删除p的某个属性时调用
    deleteProperty(target, propName) {
    
    
      console.log(`有人删除了p身上的${
      
      propName}属性,我要去更新界面了`);
      return Reflate.deleteProperty(target, propName);
    },
  });
</script>
(3) Resumen de los principios de respuesta de Vue3 ⭐

Es diferente para refyreactive

Se pasa el tipo simple de referencia: get y set de Object.defineProperty() . Por supuesto, se pasa el tipo complejo definido por ref: Proxy de reactivo

Reactive implementa la capacidad de respuesta a través de Proxy (mencionado anteriormente) y opera datos de origen a través de Reflect

De todos modos, en resumen, la novedad de vue3 es implementar capacidad de respuesta a través de Proxy para tipos de datos complejos , es decir, dos puntos:

  1. A través de Proxy : intercepta cualquier cambio en los atributos del objeto, incluyendo: adición y eliminación de atributos, lectura y escritura de valores de atributos, etc.
  2. Via Reflect : Realice las operaciones anteriores en las propiedades del objeto fuente.
new Proxy(person, {
    
    
    // 拦截读取属性值
    get(target, propName) {
    
    
      return Reflect.get(target, propName);
    },
    // 拦截设置属性值或添加属性值
    set(target, propName, value) {
    
    
      Reflate.set(target, propName, value);
    },
    // 拦截删除属性
    deleteProperty(target, propName) {
    
    
      return Reflate.deleteProperty(target, propName);
    },
});

5. Comparación entre reactivo y ref.

(1) Definir diferentes categorías de datos

  • refSe utiliza para definir datos de tipo básico.
  • reactiveSe utiliza para definir datos de tipo objeto o matriz.
  • Nota: refTambién puede definir datos de tipo objeto o matrizreactive , que se convertirán automáticamente en un objeto proxy internamente.

(2) Principios diferentes

  • se pasa ref: Object.defineProperty()y get, setpor supuesto, el tipo complejo se pasa a través de Proxy reactivo
  • reactivo se utiliza Proxypara implementar la capacidad de respuesta (mencionada anteriormente) y Reflectmanipular los datos de origen a través de

(3) Diferentes formas de uso

  • refLos datos definidos requieren .value cuando se operan y .value no es necesario para la lectura de la plantilla.
  • reactiveLos datos definidos, las operaciones y la lectura no requieren .value

6. Dos puntos a tener en cuenta durante la configuración

(1) Calendario de ejecución

setupEl tiempo de ejecución de la función es beforeCreate之前, es decir, al frente de todos los ciclos de vida . En este momento, esto no está definido, lo que significa que no se puede acceder a la instancia del componente a través de esto en la configuración .

Tenga en cuenta que beforeCreate aquí está escrito fuera de setup . Si está dentro de setup, no hay enlaces beforeCreate ni creados, porque el tiempo de ejecución de setup es equivalente a estos dos enlaces (el setup se ejecutará antes que todos los enlaces, así que simplemente escriba el código que Quiero escribir en estos dos ganchos al frente del paso )

(2)Parámetros de configuración

La configuración recibe dos parámetros:(props,context)

  1. propsEs un objeto que contiene: atributos pasados ​​desde fuera del componente y recibidos por la declaración dentro del componente.
  2. contextes un objeto que contiene tres atributos, a saberattrs、slots、emit
  • El primero attrses equivalente this.$attrsa un objeto cuyo valor se pasa desde fuera del componente pero no propsse declara en la configuración.
  • El segundo slotsequivalente this.$slotscontiene el contenido del slot recibido.
  • El tercero emites equivalente a this.$emitun evento personalizado utilizado para activar el componente.
props: ['name', 'age']
setup(props, context) {
    
    
  console.log(props) // Proxy{name:'potato',age:18}:组件外部传递过来,且组件内部声明接收了的属性。
  console.log(context.attrs)//相当于this.$attrs
  console.log(context.slots)相当于this.$slots
  console.log(context.emit)//相当于this.$emit
}

4. Funciones de cálculo y funciones de seguimiento.

1. Función calculada (calculada)

La función es la misma que en vue2, pero se convierte en una función y debe introducirse manualmente. La forma predeterminada de escribir es pasar una devolución de llamada.

Si solo usamos la abreviatura, cuando modifiquemos el valor de la propiedad calculado, aparecerá una advertencia en la consola diciéndonos que el valor de la propiedad es de solo lectura.

Esto se debe a que las propiedades calculadas son de solo lectura de forma predeterminada y cambiarán cuando cambie el valor del que dependen. Si desea cambiar el atributo calculado, debe utilizar el siguiente método de escritura completo, pasando un objeto con gettery en él setter, y setterel parámetro del medio es el nuevo valor modificado.

<template>
  <h1>个人信息</h1>
  姓:<input type="text" v-model="person.firstName" />
  <br />
  名:<input type="text" v-model="person.lastName" />
  <br />
  全名:<input type="text" v-model="person.fullName" />
  <br />
  <span>全名:{
   
   { person.fullName }}</span>
</template>

<script>
import {
      
       computed, reactive } from "vue";
export default {
      
      
  setup() {
      
      
    let person = reactive({
      
      
      firstName: "张",
      lastName: "三",
    });

    // 计算属性-简写(没有考虑计算属性被修改的情况)
    // person.fullName = computed(function () {
      
      
    //   return person.firstName + "-" + person.lastName;
    // });

    // 计算属性-完整(包括读和写)
    person.fullName = computed({
      
      
      get() {
      
      
        return person.firstName + "-" + person.lastName;
      },
      set(value) {
      
      
        const nameArr = value.split("-");
        person.firstName = nameArr[0];
        person.lastName = nameArr[1];
      },
    });

    return {
      
      
      person,
    };
  },
};
</script>

2. Función de monitoreo (reloj)

De hecho, la función de vigilancia en vue3 es la misma que en vue2, pero el método de escritura es diferente.

Cómo escribir la función de escucha de vue2 Haga clic aquí para revisar la función de escucha de vue2.

Primero preparemos algunos datos:

import {
    
     ref, reactive } from 'vue'
const sum = ref(0)
const msg = ref('hello')
const person = reactive({
    
    
	name: 'potato'
	age: 18
	job: {
    
    
		type: 'code'
		salary: 10
	}
})
(1) Cómo escribir el primer parámetro
  • Escenario 1: vue3 monitorea datos receptivos definidos por referencia
watch(sum, (newVal, oldVal) => {
    
    
	console.log("sum的值变了", newVal, oldVal);
});

Por favor agregue la descripción de la imagen.

  • Escenario 2: vue3 monitorea múltiples datos de respuesta definidos por referencia
watch([sum, msg], (newVal, oldVal) => {
    
    
	console.log("sum或msg变化了", newVal, oldVal);//new和old也是监听值构成的数组
});

Por favor agregue la descripción de la imagen.

  • Escenario 3: monitorear los datos reactivos definidos por reactivo.
    Hay dos errores aquí: el primero son reactivelos datos definidos, que no se pueden obtener en la devolución de llamada durante el monitoreo oldValue. oldValue es lo mismo que newValue
    . El segundo problema es que el monitoreo reactivede los datos definidos está habilitado de forma predeterminada deep:truey deepno se puede cambiar afalse
watch(person, (newVal, oldVal) => {
    
    
	console.log("person变化了");
},{
    
    immediate:true,deep:false});
  • Escenario 4: monitorear un atributo en los datos reactivos definidos por reactivo.
    Cabe señalar aquí que el primer parámetro debe escribirse como una función de flecha . Si escribe person.job directamente, equivale a escribir un valor muerto, que es imposible de monitorear Llegó. Además, si el trabajo es un objeto , entonces el valor predeterminado profundo es falso . Si desea un monitoreo en profundidad, debe activar manualmente deep:true (la configuración profunda es válida)
watch(()=>person.job,(newValue,oldValue)=>{
    
    
	console.log('person的job变化了',newValue,oldValue)
},{
    
    immediate:true,deep:true}) 
  • Escenario 5: monitorear algunos atributos en los datos de respuesta definidos por reactivo.
    Si esta situación es similar a la anterior, la diferencia es que el primer parámetro se escribe como una matriz, cada elemento es una función de flecha y se devuelven nuevos y antiguos. Los valores también son similares Una matriz de valores correspondientes.
watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{
    
    
	console.log('person的job变化了',newValue,oldValue)
},{
    
    immediate:true,deep:true})
(2) Si escribir .value en el primer parámetro o no

¿Qué pasa si reemplazamos persona con una definición de referencia? Entonces, ¿debería escribir durante el seguimiento .value?

import {
    
     ref, reactive } from 'vue'
const sum = ref(0)
const msg = ref('hello')
const person = ref({
    
    
	name: 'dantin'
	age: 18
	job: {
    
    
		type: 'code'
		salary: 10
	}
})

La respuesta es: escribir, porque refpara tipos de datos complejos, la capacidad de respuesta se implementa internamente, por lo que escribir de esta manera equivale a escribir datos de respuesta reactivedefinidos , lo que también tiene sus correspondientes dificultades durante el monitoreo (consulte la situación 3 arriba).Proxyreactive

watch(person.value,(newValue,oldValue)=>{
    
    
	console.log('person变化了',newValue,oldValue)
},{
    
    immediate:true,deep:false}) //此处的deep配置不奏效

Además, hay otra forma, que es monitorear a la persona (es una RefImpl对象) en profundidad, para que se pueda monitorear el valor y los cambios más profundos. Esto se debe a que si se monitorea directamente a la persona sin leer .value, entonces se monitorea el objeto RefImpl. Solo se puede monitorear cuando cambia la dirección del valor. Los cambios en el valor no se pueden monitorear, por lo que se debe activar la profundidad.

watch(person,(newValue,oldValue)=>{
    
    
	console.log('person变化了',newValue,oldValue)
},{
    
    immediate:true,deep:true}) 

Entonces, ¿por qué no se necesitan tipos de datos simples .value? De hecho, es lo mismo que el caso 4 anterior. Si el tipo de datos simple es directo .value, entonces lo que se monitorea es un valor codificado. De lo contrario .value, lo que se monitorea es un RefImplobjeto receptivo, que se puede monitorear cuando cambia el valor interno.

watch(sum,(newValue,oldValue)=>{
    
    
	console.log('sum变化了',newValue,oldValue)
})

Si es necesario .value, utilice la función de flecha para leer dinámicamente. Cada vez que cambie la suma, se ejecutará una devolución de llamada para leer el último valor.

watch(() => sum.value,(newValue,oldValue)=>{
    
    
	console.log('sum变化了',newValue,oldValue)
})

3. función de efecto de reloj

  • watchLa rutina es: especificar tanto los atributos monitoreados como las devoluciones de llamada monitoreadas .
  • watchEffectLa rutina es: no es necesario especificar qué atributo monitorear, qué atributo se usa en la devolución de llamada de monitoreo y luego monitorear qué atributo.

watchEffect es un poco como calculado, pero calculado se centra en el valor calculado (el valor de retorno de la función de devolución de llamada), por lo que se debe escribir el valor de retorno. WatchEffect presta más atención al proceso (el cuerpo de la función de devolución de llamada), por lo que no es necesario escribir un valor de retorno.

//watchEffect的回调一上来会先执行一次
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(() => {
    
    
  const x1 = sum.value;
  const x2 = person.job.salary;
  console.log("watchEffect所指定的回调执行了");
});

Supongo que te gusta

Origin blog.csdn.net/weixin_56498069/article/details/133101633
Recomendado
Clasificación