[Conceptos básicos de Vue3] 05. Componentes

Esta es una serie de documentos para Vue3 + Vite + Pinia +TS + Element-Plus. Estuve ocupado recientemente y no tengo mucho tiempo para escribir artículos, así que trate de terminar esta serie lo antes posible~

Referencias de plantilla y ciclo de vida

Antes de este capítulo, nos ocupamos de la actualización de DOM a través de la API receptiva y la representación declarativa, pero para algunas situaciones complejas que requieren la operación manual de DOM, la introducción anterior no es suficiente.

ciclo vital

Cada componente de Vue pasa por una serie de etapas de inicialización cuando se crea. Si necesitamos realizar operaciones adicionales en estas etapas, debemos llamar a los ganchos de las etapas correspondientes.

Estas etapas incluyen: configurar escuchas de datos, compilar plantillas, montar instancias en DOM y actualizar DOM cuando cambian los datos, etc. Vue ofrece oficialmente un diagrama para ayudarnos a comprender mejor el ciclo de vida:

  1. configuración : todas las API de ciclo de vida en rojo se llaman sincrónicamente durante la fase de configuración () del componente.
  2. Cuadro rojo : el ciclo de vida representado por diferentes etapas, y los ganchos de ciclo de vida subsiguientes que escribimos se ejecutarán en esta etapa.
  3. En el eje principal : representa el evento principal del componente desde la inicialización hasta la descarga.

Aquí lo presentaremos brevemente Después de presentar los ganchos del ciclo de vida, creo que comprenderá mejor esta imagen.

gancho del ciclo de vida

Después de comprender el ciclo de vida anterior, si queremos hacer algo en el ciclo correspondiente, usamos enlaces de ciclo de vida onXxx en Vue3, por ejemplo:

<configuración del guión>

importar { onMounted, onBeforeUnmount } desde 'vue'

en Montado(() => {

})

onBeforeUnmount(()=>{

})

</script>

Si has usado Vue2, notarás la diferencia:

<script>

exportación predeterminada {

creado() {

},

montado() {

},

antes de Destruir() {

}

}

</script>

El método de uso es como se escribió anteriormente, en la configuración, simplemente inyecte la devolución de llamada en la API de ciclo de vida. Aquí no haremos la comparación entre Vue2 y Vue3, es todo nuevo, según el orden del ciclo de vida:

  1. setup : beforeCreate y created se reemplazan por el método de configuración.
  2. onBeforeMount() : devolución de llamada ejecutada antes de que se monte el componente. El componente ha terminado de establecer su estado reactivo, pero aún no se han creado nodos DOM.
  3. onMounted() : ejecuta la devolución de llamada después de montar el componente. Por lo general, se usa para realizar efectos secundarios que requieren acceso al árbol DOM representado por el componente.
  4. onBeforeUpdate() : la devolución de llamada se ejecuta justo antes de que el componente actualice su árbol DOM debido a un cambio de estado reactivo. Por lo general, se usa para acceder al estado del DOM antes de que Vue actualice el DOM.
  5. onUpdated() : devolución de llamada ejecutada después de que el componente haya actualizado su árbol DOM debido a un cambio de estado reactivo. Se llamará después de que se actualice cualquier DOM del componente. Generalmente se usa para acceder al DOM actualizado. No se puede usar para actualizar el DOM aquí, lo que puede causar un bucle.
  6. onBeforeUnmount() : devolución de llamada ejecutada antes de que se desmonte la instancia del componente.
  7. onUnmounted() : devolución de llamada ejecutada después de desmontar la instancia del componente. Por lo general, se usa para limpiar manualmente algunos efectos secundarios, como temporizadores, detectores de eventos DOM o conexiones a servidores.
  8. onActivated() : Devolución de llamada ejecutada cuando el componente se activa como keep-alive.
  9. onDeactivated() : Devolución de llamada ejecutada cuando el componente se desactiva como keep-alive.
  10. onErrorCaptured() : devolución de llamada ejecutada cuando se captura un error pasado por un componente descendiente. Normalmente se utiliza para cambiar el estado de un componente para mostrar un estado de error al usuario.
  11. onRenderTracked()  solo se usa en el modo de desarrollo: se ejecuta una devolución de llamada cuando se rastrea una dependencia reactiva durante la representación del componente. Normalmente se utiliza para la depuración para rastrear las dependencias.
  12. onRenderTriggered()  solo se usa en el modo de desarrollo: se ejecuta una devolución de llamada cuando un cambio en una dependencia reactiva activa la representación de un componente. Normalmente se usa para activar la depuración actualizada.

Los anteriores son todos los ciclos de vida y sus enlaces de ciclo de vida invocables. Pasamos devoluciones de llamada en los enlaces anteriores, y Vue los activará en sus ciclos de vida.

referencia de plantilla ref

ref se utiliza para registrar referencias a elementos o subcomponentes.

La referencia de la plantilla se almacenará en la referencia que coincida con el nombre, por ejemplo, si desea cambiar el texto o la información de descripción después de cargar los datos:

<configuración del guión>

import {ref, onMounted} desde "vue";

const h2 = ref(nulo);

const img = ref(nulo);

en Montado(() => {

establecerTiempo de espera(() => {

h2.value.textContent = "Carga de datos completa";

img.value.src = "/src/activos/logotipo.svg";

}, 3000);

});

</script>

<plantilla>

<h2 ref="h2">Cargando datos...</h2>

<img ref="img" src="./activos/load.svg" alt="" />

</plantilla>

Por supuesto, también podemos hacer que h2 en el código anterior responda y usar la sintaxis de plantilla { {}} en h2 para lograrlo.

Ref. de referencia del componente

ref también se puede usar en subcomponentes, lo cual es relativamente común.

Primero explique qué es un componente:

Antes de eso, usábamos App.vue de un solo archivo. Si un proyecto escribe todo el código en este archivo, será muy difícil de mantener. Por lo tanto, dividimos las páginas reutilizables en componentes y separamos las páginas de la lógica. , referenciado por otros páginas mediante la importación de componentes.

<configuración del guión>

importar niño desde './Child.vue'

</script>

<plantilla>

<Niño ref="niño" />

</plantilla>

Usando ref, el componente principal puede obtener el componente secundario. Ejemplo:

<configuración del guión>

importar {ref, onMounted} desde 'vue'

importar niño desde './Child.vue'

const hijo = ref(nulo)

en Montado(() => {

})

</script>

<plantilla>

<Niño ref="niño" />

</plantilla>

Cabe señalar que el componente secundario no utiliza <configuración de script>, la instancia del componente al que se hace referencia es exactamente la misma que la del componente secundario, y el componente principal tiene acceso a todas las propiedades y métodos del componente secundario.

Si se usa <script setup>, los subcomponentes son privados por defecto a menos que se expongan explícitamente usando defineExpose.

Por supuesto, en la mayoría de los casos, la interacción entre los componentes padre e hijo se puede lograr usando props y emit sin usar ref.

Props de valor de pase de componente

Los métodos para pasar valores entre componentes se pueden resumir en tres categorías: pasar valores entre componentes padre e hijo, pasar valores entre componentes hermanos y pasar valores entre componentes relativos lejanos.

Hay dos API que Vue proporciona a nuestros componentes para pasar valores: props y emit. Entre ellos, podemos pasar valores de componentes padre => hijo a través de accesorios.

Durante el proceso de desarrollo, necesitamos especificar los accesorios del subcomponente a través de defineProps(). El componente principal puede pasar valores al igual que declarar parámetros HTML, o usar: (abreviatura v-bind) para pasar valores dinámicamente:

<!-- componente principal -->

<configuración del guión>

importar {ref} de "vue";

importar niños desde "./components/Children.vue";

const hola = ref("Hola");

</script>

<plantilla>

<input v-model="hola" />

<Mensaje para niños="hhh" :activeMsg="hola" />

</plantilla>

<!-- Subcomponentes -->

<script lang="ts" configuración>

importar { onMounted } desde "vue";

const apoyos = defineProps({

mensaje: Cadena,

mensaje activo: Cadena

});

en Montado(() => {

console.log("accesorios", accesorios);

});

</script>

<plantilla>

<span>mensaje: { { mensaje }}</span>

<span>mensaje activo: { { mensaje activo }}</span>

</plantilla>

Después de la declaración defineProps(), los datos que contiene se pueden usar en la plantilla del componente secundario. El acceso en JavaScript requiere acceso a través del objeto devuelto por defineProps().

Aviso:

  1. los accesorios son de solo lectura, siga el flujo de datos de un solo elemento, cuando intente modificar los accesorios advertirá que solo es de lectura.
  2. Cuando los datos definidos en js tienen el mismo nombre que en props, se usa el definido en js.

const activeMsg = "hl";

<span>mensaje activo: { { mensaje activo }}</span>

  1. props proporciona opciones de validación para garantizar que el proyecto no use TypeScript para la detección de tipos y también puede determinar un determinado tipo de datos para evitar datos que no cumplan con los requisitos de tipo. (Ahora que Vue3 admite TypeScript, se puede decir que esto no es muy útil)

interfaz DataProps {

mensaje: Cadena;

mensaje activo: Cadena;

}

const props = defineProps<DataProps>();

Emisión de evento de escucha de componente

Los componentes secundarios usan emit() para pasar datos al componente principal. El primer parámetro es el nombre del evento y otros parámetros adicionales se pasarán directamente a la función de escucha del componente principal.

El componente principal usa @ (v-on) para monitorear el tiempo del componente secundario y puede recibir parámetros pasados ​​por el componente secundario.

<!-- componente principal -->

<plantilla>

<Niños @response="(mensaje) => (hola = mensaje)" />

{ { hola }}// Después de hacer clic en el botón del subcomponente, se convierte en hola desde niño

</plantilla>

<configuración del guión>

importar {ref} de "vue";

importar niños desde "./components/Children.vue";

const hola = ref("Hola");

</script>

<!-- Subcomponentes -->

<plantilla>

<button @click="emit('response', 'hola from child')">emit</button>

</plantilla>

<script lang="ts" configuración>

const emit = defineEmits(["respuesta"]);

</script>

Aviso:

  1. La sintaxis de $emit se puede usar en la plantilla, y solo se puede usar defineEmits en js para devolver el objeto emit para desencadenar el evento.
  2. Los eventos desencadenantes se pueden marcar con tipo para tener un control más preciso sobre los eventos desencadenados.

const emit = defineEmits<{

(e: 'respuesta', mensaje: cadena): vacío

}>()

Plantilla de transferencia - ranura ranura

Además de pasar datos, los componentes principales también pueden pasar plantillas a componentes secundarios a través de ranuras.

<!-- componente principal -->

<plantilla>

<Children>contenido del botón de tragamonedas</Children>

</plantilla>

<configuración del guión>

importar niños desde "./components/Children.vue";

</script>

<!-- Subcomponentes -->

<plantilla>

<botón><ranura /></botón>

</plantilla>

<secuencia de comandos lang="ts" configuración></secuencia de comandos>

contenido predeterminado

Si desea establecer el contenido predeterminado, por ejemplo, el componente principal no pasa caracteres de plantilla al componente secundario, pero el contenido del botón del componente secundario tiene el contenido predeterminado:

<!-- componente principal -->

<plantilla>

<Niños></Niños>

</plantilla>

<configuración del guión>

importar niños desde "./components/Children.vue";

</script>

<!-- Subcomponentes -->

<plantilla>

<botón>

<ranura>

contenido

</ranura>

</botón>

</plantilla>

<secuencia de comandos lang="ts" configuración></secuencia de comandos>

ranura con nombre

Si el componente contiene varios enchufes, debe usar un enchufe con nombre para darle al enchufe un ID único para determinar el contenido que se representará en diferentes enchufes.

<!-- componente principal -->

<plantilla>

<Niños>

<template v-slot:header> Encabezado </template>

<template v-slot:button> contenido del botón de ranura </template>

</Niños>

</plantilla>

<configuración del guión>

importar niños desde "./components/Children.vue";

</script>

<plantilla>

<div><nombre de ranura="encabezado" /></div>

<botón><nombre de la ranura="botón" /></botón>

</plantilla>

<secuencia de comandos lang="ts" configuración></secuencia de comandos>

La ranura en V se puede abreviar como #, ranura en V: encabezado => # encabezado. Y v-slot también puede aceptar parámetros dinámicos (nombre de ranura dinámica): #[dynamicSlotName] .

Ranuras con alcance

Las ranuras mencionadas anteriormente no pueden acceder al estado de los subcomponentes. En algunos escenarios, queremos que los subcomponentes pasen datos a las ranuras, y las ranuras con ámbito pueden cumplir este requisito.

<!-- componente principal -->

<plantilla>

<Niños>

<template v-slot:header="slotProps"> { { slotProps.msg }}</template>

</Niños>

</plantilla>

<configuración del guión>

importar niños desde "./components/Children.vue";

</script>

<!-- Subcomponentes -->

<plantilla>

<tipo de entrada="texto" v-modelo="mensaje" />

<div><ranura nombre="encabezado" :msg="mensaje" /></div>

</plantilla>

<script lang="ts" configuración>

importar {ref} de "vue";

mensaje constante = ref("");

</script>

Para ser precisos, el ejemplo anterior es una ranura de alcance con nombre. Si se trata de una ranura de alcance común, basta con cambiar la ranura con nombre de la plantilla a una ranura común.

combate

Las secciones anteriores hablaron sobre los ganchos del ciclo de vida de los componentes, los accesorios del paso del valor del componente, la emisión de eventos desencadenantes y la comprensión y la aplicación de la ranura de la plantilla.

La función de visualización de lista del blog proporciona la función de clasificación.

  1. Los datos clasificados provienen del componente principal y el tipo seleccionado se notifica al componente principal a través de la devolución de llamada.
  2. El componente principal de la lista se usa para controlar el contenido y el estilo del elemento, y el componente secundario se usa para operaciones generales, como el ciclo básico de la lista.

Los ejemplos incluyen tanto como sea posible el conocimiento que hemos aprendido en este capítulo.Si la siguiente parte del código no se puede entender, significa que no ha entendido esa parte del conocimiento con claridad.

Los ejemplos en esta sección incluyen confirmación de tipo para algunos ts

Componente principal  App.vue :

<script lang="ts" configuración>

import { reactivo, ref, onMounted } de "vue";

importar niños desde "./components/Children.vue";

importar ClassifyHeader desde "./components/ClassifyHeader.vue";

const etiquetas = reactivo ({

lista: ["vue", "reaccionar"],

marcado: [],

});

función marcadaEtiquetas(marcada) {

etiquetas.marcado = marcado;

obtener datos();

}

en Montado(() => {

obtener datos();

});

const listRef = ref();

función getData() {

const params = { tags: tags.checked, página: 1 };

console.log("Solicitar parámetros:", params);

establecerTiempo de espera(() => {

datos constantes = [

{ título: "JavaScript Beginner to Master", nombre de usuario: "Chocolate 1999", fecha: "2023-02-11" },

{título: "Vue3 实战", nombre de usuario: "HearLing", fecha: "2023-03-09"},

];

listRef.value.loadData(datos);

}, 1000);

}

</script>

<plantilla>

<ClassifyHeader :tags="tags.list" @select="checkedTags" />

<Niños ref="listRef">

<template #item="{título, nombre de usuario, fecha}">

<div clase="elemento">

<p>{ { título }}</p>

<p class="meta">Autor: { { nombre de usuario }} | Hora: { { fecha }}</p>

</div>

</plantilla>

</Niños>

</plantilla>

<estilo de alcance></estilo>

El componente principal implica puntos de conocimiento:

  1. Pase el valor con el componente de clasificación ClassifyHeader. apoyos y emitir.
  2. Ciclo de vida en Montado. Solicite datos después de montar el componente.
  3. Referencia del componente ref. método de uso de componentes secundarios.
  4. Ranuras de alcance con nombre.

Componentes principales y componentes de categoría

En el componente principal, el valor inicial  de tags.list  se pasa al componente secundario a través de accesorios y se escucha el evento de selección. El activador de selección ejecutará la función de etiquetas marcadas y el componente principal obtendrá el valor marcado y realizará una operación para volver a solicitar los datos de la lista.

componentes/ ClassifyHeader.vue  clasificar componente:

<!-- Categoría-->

<plantilla>

<div v-for="elemento en props.tags">

<tipo de entrada="casilla de verificación" :valor="elemento" @click="seleccionar(elemento)" />

{ { elemento }}

</div>

</plantilla>

<script lang="ts" configuración>

const props = defineProps(["etiquetas"]);

const emit = defineEmits<{

(e: "seleccionar", verificado: cadena []): vacío;

}>();

const comprobado: cadena[] = [];

selección de función (elemento) {

índice const = comprobado.indexOf(elemento);

si (índice! == -1) {

comprobado.empalme(índice, 1);

} demás {

comprobado.push(elemento);

}

emit("seleccionar", verificado);

}

</script>

<estilo lang="scss" alcance></estilo>

El componente de clasificación ClassifyHeader sirve principalmente para registrar la categoría seleccionada y pasar los datos al componente principal a través de emit.

Componentes principales y de lista

El componente principal obtiene la instancia del componente secundario a través de ref y usa el método loadData expuesto por el componente secundario para cargar los datos. El componente secundario pasa datos al componente principal a través de la ranura del alcance y el componente principal controla el diseño del contenido.

componentes/ componente de la lista Children.vue  :

<!-- Subcomponentes -->

<script lang="ts" configuración>

importar {ref} de "vue";

Elemento de interfaz {

título: cadena;

nombre de usuario: cadena;

fecha: cadena;

}

elementos const = ref<Elemento[]>([]);

const loadData = (datos) => {

elementos.valor = datos;

};

definirExponer({

Cargar datos,

});

</script>

<plantilla>

<ul>

<li v-if="!items.length">Cargando...</li>

<li v-for="elemento en elementos">

<ranura nombre="elemento" v-bind="elemento" />

</li>

</ul>

</plantilla>

<estilo de alcance></estilo>

Los subcomponentes proporcionan ranuras con nombre y usan defineExpose para lanzar el método loadData para que el componente principal pase por el ejemplo del componente.

Para los ejemplos anteriores, hemos revisado la mayor parte del conocimiento en la práctica. Se sugiere que pueda escribir estos códigos usted mismo para profundizar su impresión.

Otras formas de pasar valores

Además de los accesorios mencionados anteriormente, emite valores de paso de componentes padre-hijo. También puede usar la API de inyección de dependencia: proporcionar, inyectar.

  1. provide() : Proporcione un valor que puedan inyectar los componentes descendientes. Uso: provide(/* nombre de inyección  /'mensaje', /  valor*/'¡hola!').
  2. inject() : Inyecta los datos proporcionados por el componente superior. Uso: const mensaje = inyectar ('mensaje') .

Los componentes de Brother pueden controlar la transferencia de datos a través del componente principal.

Para la comunicación entre componentes, podemos usar herramientas de gestión de estado, como Pinia, que aprenderemos más adelante, es un marco de gestión de estado.

Resumir

En este capítulo, primero combinamos el diagrama de flujo del ciclo de vida de Vue para dar ejemplos del tiempo de activación de cada gancho del ciclo de vida y los escenarios de uso de algunos ganchos. Luego habló sobre el rol de ref, y finalmente terminó la charla y practicó las API relacionadas con la comunicación de componentes.

Hasta ahora, el conocimiento básico de Vue3 ha terminado aquí, y todavía queda una pequeña parte por explorar en nuestros cursos de combate reales.

Si no ha estudiado TypeScript, también he preparado los conocimientos básicos de TypeScript. El curso no será muy largo y le mostraré algunos conocimientos de TypeScript de uso común para prepararse para el combate real.

 

Supongo que te gusta

Origin blog.csdn.net/qq_39154376/article/details/131929703
Recomendado
Clasificación