コンポーネントの再帰
モジュールを書くとき、データがどのくらい入れ子になっているかが分からないので、コンポーネントの要素構造にどれだけ入れ子が繰り返されているかが分かりませんが、この時に使用するテンプレートは静的テンプレートですが、Vue
入れ子の深さを表現しきれない現象が発生します。
したがって、このシナリオでは、コンポーネントの再帰の概念が使用されます。これは、独自のコンポーネントを独自のコンポーネントで使用することを意味します。
重要なのは注意を払うことです
- コンポーネントに名前を付けます (
name
属性を追加します)。 - 渡されるパラメータは、再帰操作を完了でき、再帰終了できる必要もあります。
- コンポーネントにイベント登録がある場合、参照先のコンポーネントに対してイベントを登録する必要があります。
ここに例があります
ネストされたレベルのシーンが頻繁に発生するため、そのほとんどはディレクトリ レベルにあります。次に、Vue
ディレクトリ レベルのテンプレートの例を示します。
Catalogue.vue
データがArray
親コンポーネントから渡された型配列であるコンポーネントを書きたいとします。そのdata
構成は次のとおりです。
<script>
export default {
name: "Catalogue",
props: {
/* 数据的结构简示
[
{
name: "xxx",
isSelcet: false,
},
{
name: "yyy",
isSelcet: false,
children: [
{
name: "zzz",
isSelect: true
}
]
}
]
*/
list: {
type: Array,
// 如果要返回数组的话, 这里必须是一个函数,直接写数组是不行的
default: () => [],
},
},
};
</script>
次に、そのデータに基づいて、そのテンプレート構造がリストの形式で記述できることがわかります。ルート コンポーネントはコンテナーであり、ul
内部li
リストはデータの量と深さに関連しています。したがって、最初に次のようにすることができます。list
次のコードに示すように、属性に従ってトラバースして、最も外側のレイヤー テンプレートを取得します。
<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>
list
ただし、明らかに、この書き方では 1 つのレイヤーしか表示できません。プロパティに基づいてネストの深さが不明なコンポーネントを表示したい場合は、次のコードに示すように、構成内のプロパティに基づいてコンポーネントの再帰を実行するchildren
必要があります。Vue
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>
これでテンプレート構造の完成に相当しますが、コンポーネントの内部イベント登録を伴う場合は、以下のコードのように他のイベント登録処理を行う必要があります。
コンポーネント内の要素がspan
クリック イベントを登録する必要があり、このイベントはこのコンポーネントでは処理できないと仮定します。イベントはselect
親要素にスローされる必要があります。これは、次のテンプレートと構成を意味します。
<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>
ここの問題は明らかです。実行中、ネストの最初のレベルのみがspan
クリック イベントを登録し、他のより深いレベルはspan
クリック イベントを登録しません。その後、再帰的にこれに基づいていくつかの変更を加える必要があります。コンポーネントは ** イベントselect
**を登録します。繰り返しますが、コードは次のとおりです
<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
イベントを登録する場合handlerClick
、関数名を指定するだけで済みます。このコンポーネントはサブコンポーネントのサブコンポーネントに相当するため、この関数を処理する方法はなく、上向きにイベントをスローし続ける必要があります。 、パラメータselect
とitem
イベントの名前が親コンポーネントに渡されるようにする
知らせ
再帰コンポーネントのイベントを登録する場合、それ自体と一致させるitem
方法がないためパラメーターを渡すことはできませんitem
。そのため、パラメーターを使用するときに自動的に取得される関数名のみが必要です。