récursivité des composants
Lorsque nous écrivons un module, parce que nous ne savons pas à quelle profondeur les données sont imbriquées, nous ne savons pas combien d'imbrications répétées il y a dans la structure des éléments du composant.Le modèle que nous utilisons actuellement est un modèle statique, nous le ferons donc. Vue
Il existe un phénomène qui ne peut pas exprimer pleinement la profondeur de nidification.
Par conséquent, dans ce scénario, le concept de récursivité des composants sera utilisé, ce qui signifie utiliser vos propres composants dans vos propres composants.
La clé est de faire attention
- Nommer le composant (ajouter
name
des attributs) - Les paramètres passés doivent également pouvoir terminer l'opération récursive et avoir une sortie récursive.
- Lorsqu'il y a une inscription d'événement dans un composant, l'événement doit être enregistré pour le composant référencé.
Voici un exemple
Des scènes de niveaux imbriqués se produisent souvent, la plupart d'entre elles se trouvent donc au niveau du répertoire. Voici un Vue
exemple de modèle au niveau du répertoire.
Supposons que nous voulions écrire un composant Catalogue.vue
dont les données sont un Array
tableau de types qui lui est transmis par le composant parent. Sa data
configuration est la suivante
<script>
export default {
name: "Catalogue",
props: {
/* 数据的结构简示
[
{
name: "xxx",
isSelcet: false,
},
{
name: "yyy",
isSelcet: false,
children: [
{
name: "zzz",
isSelect: true
}
]
}
]
*/
list: {
type: Array,
// 如果要返回数组的话, 这里必须是一个函数,直接写数组是不行的
default: () => [],
},
},
};
</script>
Ensuite, sur la base de ses données, nous pouvons savoir que sa structure de modèle peut être écrite sous la forme d'une liste. Le composant racine est un conteneur ul
, et la li
liste interne est liée à la quantité et à la profondeur des données. Par conséquent, nous pouvons d'abord list
parcourir en fonction des attributs pour obtenir le modèle de couche le plus externe, comme indiqué dans le code suivant
<template>
<ul class="catalogue-container">
<li v-for="(item, i) in list" :key="i">
<span :class="{'active': item.isSelect}"> {
{ item.name }} </span>
</li>
</ul>
</template>
Mais évidemment, cette façon d'écrire ne peut afficher qu'un seul calque. Si vous souhaitez afficher des composants avec une profondeur d'imbrication inconnue en fonction des list
propriétés children
, vous devez effectuer une récursivité des composants en fonction des propriétés Vue
de la configuration , comme indiqué dans le code suivant.name
<template>
<ul class="catalogue-container">
<li v-for="(item, i) in list" :key="i">
<span :class="{'active': item.isSelect}"> {
{ item.name }} </span>
/* 进行组件递归,知道item.children为空 */
<Catalogue :list="item.children">
</li>
</ul>
</template>
Cela équivaut à l'achèvement de la structure du modèle. Si cela implique l'enregistrement d'événements internes du composant, d'autres traitements d'enregistrement d'événements doivent être effectués, comme indiqué dans le code suivant.
Supposons que les éléments à l'intérieur du composant span
doivent enregistrer un événement de clic et que cet événement ne peut pas être géré dans ce composant. Un select
événement doit être lancé vers l'élément parent, ce qui signifie le modèle et la configuration suivants :
<template>
<ul class="catalogue-container">
<li v-for="(item, i) in list" :key="i">
<span
:class="{'active': item.isSelect}"
@click="handlerClick(item)"
> {
{ item.name }} </span>
/* 进行组件递归,知道item.children为空 */
<Catalogue :list="item.children">
</li>
</ul>
</template>
<script>
export default {
methods: {
handlerClick(item) {
console.log("Catalogue", item);
this.$emit("select", item);
},
},
};
</script>
Le problème ici est évident. Lors de l'exécution, seul le premier niveau d'imbrication span
enregistre les événements de clic, et les autres niveaux plus profonds span
n'enregistrent pas les événements de clic. Vous devez ensuite apporter quelques modifications sur cette base pour que le composant enregistre de manière récursive l'** select
événement**. encore une fois, le code est le suivant
<template>
<ul class="catalogue-container">
<li v-for="(item, i) in list" :key="i">
<span
:class="{'active': item.isSelect}"
@click="handlerClick(item)"
> {
{ item.name }} </span>
<Catalogue
:list="item.children"
@select="handlerClick"
>
</li>
</ul>
</template>
<script>
export default {
methods: {
handlerClick(item) {
console.log("Catalogue", item);
this.$emit("select", item);
},
},
};
</script>
select
Lors de l'enregistrement d'un événement ici , il vous suffit de donner handlerClick
un nom de fonction, car ce composant est équivalent à un sous-composant d'un sous-composant, il n'y a donc aucun moyen de traiter cette fonction et vous devez continuer à lancer des événements vers le haut. , afin que les paramètres select
et item
événements Nom soient transmis au composant parent
Avis
Lors de l'enregistrement d'un événement pour un composant récursif, vous ne pouvez pas transmettre de paramètres item
car il n'y a aucun moyen de item
le faire correspondre avec lui-même, vous n'avez donc besoin que du nom de la fonction, qui sera automatiquement apporté lors de l'utilisation des paramètres.