Répertoire des articles de la série
contenu | Lien de référence |
---|---|
Utilisation de base de Vue | L'utilisation de base de Vue (un article pour maîtriser les points de connaissance les plus élémentaires de Vue) |
Communication Vue et fonctionnalités avancées | Communication entre composants Vue et fonctionnalités avancées (communication entre différents composants, v-model personnalisé, nextTick, slots) |
Fonctionnalités avancées de Vue | Fonctionnalités avancées de Vue (composants dynamiques, chargement asynchrone, keep-alive, mixin, Vuex, Vue-Router) |
Vue Principe 1 | Principe de Vue (compréhension du modèle MVVM, modification approfondie/surveillance des données, surveillance des modifications de la baie, compréhension approfondie du DOM virtuel) |
Vue Principe 2 | Principe de Vue (algorithme diff, compilation de modèles, rendu et mise à jour de composants, routage d'implémentation JS) |
Questions d'entretien chez Vue | Site de test à haute fréquence d'entretiens front-end Web - Questions d'entretien Vue |
Annuaire d'articles
1. Communication entre les composants Vue
1. props et $emit
props
fréquemment utilisépère en filstransmettre des donnéesthis.$emit
fréquemment utiliséfils à pèretransmettre des donnéesevent.$emit
fréquemment utiliséchambre fratrietransmettre des données
Exemple : deux sous-composants (composant de zone de saisie et composant de liste) sont dynamiquement ajoutés et supprimés
Composant parent (index.vue)
- Liaisons du composant parent et événement personnalisé
@add
sur l'étiquette du composant enfant@delete
<template>
<div>
<Input @add="addHandler" />
<List :list="list" @delete="deleteHandler" />
</div>
</template>
<script>
import Input from "./Input";
import List from "./List";
export default {
components: {
Input,
List,
},
data() {
return {
list: [
{
id: "id-1",
title: "标题1",
},
{
id: "id-2",
title: "标题2",
},
],
};
},
methods: {
// 添加项目
addHandler(title) {
this.list.push({
id: `id-${
Date.now()}`,
title,
});
},
// 删除项目
deleteHandler(id) {
this.list = this.list.filter((item) => item.id !== id);
},
},
// 创建
created() {
console.log("index created");
},
// 挂载
mounted() {
console.log("index mounted");
},
// 更新前
beforeUpdate() {
console.log("index before update");
},
// 更新
updated() {
console.log("index updated");
},
};
</script>
composant enfant (input.vue)
- Liaison de bouton événement addTitle
this.$emit('add', this.title)
Appelez l'événement du composant parent en utilisant- Utiliser
event.$emit("onAddTitle", this.title)
pour appeler des événements personnalisés (événements définis par des composants frères)
<template>
<div>
<input type="text" v-model="title" />
<button @click="addTitle">add</button>
</div>
</template>
<script>
import event from "./event";
export default {
data() {
return {
title: "",
};
},
methods: {
addTitle() {
// 调用父组件的事件
if (this.title.trim() !== "") {
this.$emit("add", this.title);
// 调用自定义事件
event.$emit("onAddTitle", this.title);
this.title = "";
} else {
alert('输入内容不能为空')
}
},
},
};
</script>
Composant enfant (List.vue)
- Utilisez les props pour recevoir la liste du composant parent et faire des restrictions de type et des valeurs par défaut
- Le bouton est lié à la fonction deleteItem, qui utilise l'événement d'
this.$emit("delete", id)
appel du composant parent et le supprime en fonction de l'id event.$on("onAddTitle", this.addTitleHandler)
Lier des événements personnalisés lors du montageevent.$off("onAddTitle", this.addTitleHandler)
Détruire les événements personnalisés avant la destruction (beforeDestroy)- Remarque : lors de la liaison et de la destruction d'événements personnalisés, le deuxième paramètre est une fonction ordinaire transmise, n'écrivez pas de fonctions fléchées (ce point changera)
<template>
<div>
<ul>
<li v-for="item in list" :key="item.id">
{
{
item.title }}
<button @click="deleteItem(item.id)">删除</button>
</li>
</ul>
</div>
</template>
<script>
import event from "./event";
export default {
// props: ['list']
props: {
// prop 类型和默认值
list: {
type: Array,
default() {
return []
}
},
},
methods: {
deleteItem(id) {
this.$emit("delete", id);
},
addTitleHandler(title) {
console.log("on add title", title);
},
},
created() {
console.log("list created");
},
mounted() {
console.log("list mounted");
// 绑定自定义事件
event.$on("onAddTitle", this.addTitleHandler);
},
beforeUpdate() {
console.log("list before update");
},
updated() {
console.log("list updated");
},
beforeDestroy() {
// 及时销毁,否则可能造成内存泄露
event.$off("onAddTitle", this.addTitleHandler);
},
};
</script>
fichier event.js
- Créez une instance de vue, vous pouvez utiliser des méthodes telles que
$emit
,$off
,$on
etc.
import Vue from 'vue'
export default new Vue()
Ligne de séparation------------------------------------------------ -------------------------------------------------- ---------
Ligne de séparation------------------------------------------------ -------------------------------------------------- ---------
Ligne de séparation------------------------------------------------ -------------------------------------------------- ---------
2. Cycle de vie
Cycle de vie détaillé [lien de référence]
- beforeCreate : l'instance de vue est créée, el et les données n'ont pas été initialisées, ne peuvent pas accéder aux données et à la méthode, ne fonctionnent généralement pas à ce stade.Ne fonctionnent généralement pas à ce stade
- created : les données et la méthode dans l'instance de vue ont été initialisées et les propriétés ont été liées. Mais pour le moment, il s'agit toujours d'un DOM virtuel, le vrai DOM n'a pas été généré et $el n'est pas encore disponible.Les données sont généralement initialisées ici
- beforeMount : le modèle a été compilé, mais il n'a pas été rendu dans la page (c'est-à-dire que le dom virtuel est chargé dans le dom réel)
- monté : le modèle a été rendu dans un véritable DOM et l'utilisateur peut déjà voir la page rendue. Après avoir exécuté monté, cela signifie que l'instance a été complètement créée
- beforeUpdate : déclenché avant le nouveau rendu, puis le mécanisme de dom virtuel de vue reconstruira le dom virtuel et restituera après avoir comparé le dernier arbre de dom virtuel avec l'algorithme diff. Seules les modifications de données sur la vue se déclencheront avant la mise à jour et la mise à jour, et seules les modifications de données dans les données ne se déclencheront pas.
- mis à jour : les données ont été modifiées et le dom est restitué.
- beforeDestroy : Exécuté avant la destruction (lorsque la méthode $destroy est appelée), généralement ici : efface les timers, efface les événements liés personnalisés, etc...
- détruit : après la destruction (l'élément Dom existe, mais n'est plus contrôlé par vue), désinstallez l'observateur, l'écouteur d'événement et les composants enfants.
En se référant aux résultats des exemples d'accessoires et de $emit, le cycle de vie du composant parent-enfant est résumé comme suit :
01.父组件 before create
02.父组件 created
03.父组件 before mount
04.子组件 before create
05.子组件 created
06.子组件 before mount
07.子组件 mounted
08.父组件 mounted
09.父组件 before update
10.子组件 before update
11.子组件 updated
12.父组件 updated
13.父组件 before destroy
14.子组件 before destroy
15.子组件 destroyed
16.父组件 destroyed
Deuxièmement, les fonctionnalités avancées de Vue
Modèle en V personnalisé, $nextTick, slot, dynamique, composants asynchrones, keep-alive, mixin
1. Personnalisez le modèle en V
Exemple : modèle en V d'implémentation personnalisée
Composant enfant CustomVModel.vue
- entrée utilisée : valeur au lieu de v-model
- l'attribut change1 correspond à
- l'attribut text1 correspond à
- Prop est la propriété qui est liée à l'aide de la directive v-model dans le composant parent qui appelle le composant
- event correspond à une fonction qui modifie la valeur de la propriété spécifiée par prop
<template>
<input
type="text"
:text="text1"
@input="$emit('change1', $event.target.value)"
/>
</template>
<script>
export default {
name: "CustomVModel",
model: {
prop: "text1", // 对应 props text1
event: "change1",
},
props: {
type: String,
default() {
return "";
},
},
};
</script>
composant parent index.vue
- Utiliser le nom de liaison de données bidirectionnelle v-model sur l'étiquette du composant enfant
<template>
<div>
<p>vue 高级特性</p>
<hr />
<p>{
{
name }}</p>
<CustomVModel v-model='name'/>
</div>
</template>
<script>
import CustomVModel from "./CustomVModel.vue";
export default {
name: "index",
components: {
CustomVModel },
data() {
return {
name: '杂货铺'
}
}
};
</script>
2、nextTick
- Vue est un rendu asynchrone
- Une fois les données modifiées, le DOM ne sera pas rendu immédiatement
- $nextTick sera déclenché après le rendu DOM pour obtenir le dernier nœud DOM
Exemple : Ajouter des nœuds enfants et obtenir la longueur totale des nœuds enfants
Composant NextTick.vue
- ref est utilisé pour le marquage
- les références sont utilisées pour obtenir des éléments DOM
this.$nextTick(() => {...})
Pour le rendu asynchrone, rappel après le rendu du DOM- S'il n'est pas ajouté
$nextTick
, le résultat de sortie est 3
<template>
<div>
<ul ref="ul1">
<li v-for="(item, index) in list" :key="index">
{
{
item }}
</li>
</ul>
<button @click="addItem">添加一项</button>
</div>
</template>
<script>
export default {
name: "NextTick",
data() {
return {
list: ["a", "b", "c"],
};
},
methods: {
addItem() {
this.list.push(`${
Date.now()}`);
this.list.push(`${
Date.now()}`);
this.list.push(`${
Date.now()}`);
// 异步渲染,$nextTick 待 DOM 渲染完再回调
// 页面渲染时会将 data 的修改做整合,多次 data 修改只会渲染一次
this.$nextTick(() => {
// 获取 DOM 元素
const ulElem = this.$refs.ul1;
console.log(ulElem.childNodes.length); // 6
});
},
},
};
</script>
3. Fente d'emplacement
(1) Emplacement par défaut
- Permet aux composants parents d'insérer
html
des structures <solt>
Le corps de l'étiquette est le contenu par défaut, c'est-à-dire que lorsque le composant parent ne définit pas de contenu, il s'affiche ici
Exemple : Utilisation de base des emplacements par défaut
composant parent index.vue
- À l'intérieur de la balise de composant enfant du composant parent
{ { website.title }}
se trouve le contenu à rendre dans l'emplacement du composant enfant
<template>
<div>
<p>vue 高级特性</p>
<hr />
<SlotDemo :url="website.url">
{
{
website.title }}
</SlotDemo>
</div>
</template>
<script>
import SlotDemo from "./SlotDemo.vue";
export default {
components: {
SlotDemo },
data() {
return {
website: {
url: "http://baidu.com/",
title: "Baidu",
subTitle: "百度",
},
};
},
};
</script>
Sous-composant SlotDemo.vue
- Lorsqu'il y a du contenu dans la balise de composant enfant du composant parent, le contenu correspondant est rendu
- Le contenu par défaut de l'emplacement est rendu lorsqu'il n'y a pas de contenu dans la balise du composant enfant du parent
<template>
<a :href="url">
<slot>
默认内容,即父组件没设置内容时,这里显示
</slot>
</a>
</template>
<script>
export default {
props: ['url'],
};
</script>
Ligne de séparation------------------------------------------------ -------------------------------------------------- ---------
(2) Fente pour lunette
- Scénario : Le contenu d'un emplacement peut souhaiter utiliser des données provenant à la fois du domaine du parent et du domaine de l'enfant
Exemple : Afficher le titre du composant enfant, utiliser le lien du composant parent
composant parent index.vue
- Défini à l'intérieur de la balise de composant enfant du composant parent
<template>
<template>
Utilisez v-slot pour lier les propriétés personnalisées slotProps dans l'étiquette- Obtenez ensuite la valeur du titre du sous-composant via slotProps.soltData.title
<template>
<div>
<p>vue 高级特性</p>
<hr />
<ScopedSlot:url="website.url">
<template v-slot="slotProps">
{
{
slotProps.slotData.title }}
</template>
</ScopedSlot>
</div>
</template>
<script>
import ScopedSlot from "./ScopedSlot.vue";
export default {
components: {
ScopedSlot},
data() {
return {
website: {
url: "http://baidu.com/",
title: "Baidu",
subTitle: "百度",
},
};
},
};
</script>
Sous-composant ScopedSlot.vue
<slot>
Personnalisez l'attribut dynamique slotData dans la balise, liez le site Web dans les données- Afficher le titre du composant enfant en utilisant la syntaxe d'interpolation dans la balise
<template>
<a :href="url">
<slot :slotData="website">
{
{
website.subTitle }}
</slot>
</a>
</template>
<script>
export default {
props: ["url"],
data() {
return {
website: {
url: "http://bilibili.com/",
title: "Bilibili",
subTitle: "哔哩哔哩",
},
};
},
};
</script>
(3) Emplacement nommé
- Utiliser dans
<slot>
les sous-name='xxx'
pour nommer l'emplacement <template>
Utiliser dans l'emplacement du composant parentv-slot:xxx
ou du composant enfant#xxx
correspondant
Exemple : utilisation d'emplacements nommés
composant parent index.vue
<template>
Utiliser dans l'emplacement du composant parentv-slot:xxx
ou du composant enfant#xxx
correspondant
<template>
<div>
<p>vue 高级特性</p>
<hr />
<NamedSlot>
<template v-slot:header>
<h4>将插入到 header slot 中</h4>
</template>
<p>将插入到 main slot 中,即未命名的 slot</p>
<template #footer>
<p>将插入到 footer slot 中</p>
</template>
</NamedSlot>
</div>
</template>
<script>
import NamedSlot from "./NamedSlot.vue";
export default {
components: {
NamedSlot }
};
</script>
Sous-composant NamedSlot.vue
- Utiliser dans
<slot>
les sous-name='xxx'
pour nommer l'emplacement
<template>
<div>
<header>
<slot name="header">默认头部</slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer">默认尾部</slot>
</footer>
</div>
</template>
<script>
export default {
};
</script>
不积跬步无以至千里 不积小流无以成江海
Cliquez pour suivre et ne vous perdez pas, continuez à mettre à jour...