原文地址:Building Recursive components in Vue
几天前,我想构建一个 Vue 组件,它能够显示嵌套节点树,但我们不知道确切的嵌套数量 - 因此它需要能够递归工作。我很惊讶网络上没有太多关于它的资源,所以我决定写一篇关于它的文章。
主要思想是让一个组件接受数据属性(目前数据结构未知)和另外两个属性用于summary
open
;第一个用于定义details
标签中使用的名称和显示的文本,第二个用于查看节点树是否打开。
我希望你会喜欢它:)
在 Vue 中构建递归组件
在此示例中,我使用 VueUse onClickOutside
工具函数来处理外部单击操作(我就是喜欢这个工具!)。
首先,让我们定义该组件将接受的 props:
const props = defineProps({
summary: {
type: String,
default: 'disclosure'
},
open: {
type: Boolean,
default: false
},
content: {
type: Object,
default: () => ({})
}
})
接下来,让我们定义反应式引用和计算变量:
const computedOpenState = ref(props.open)
const details = ref(null)
const hasNestedChildren = computed(() => props.content.children?.length)
最后,在脚本标签的最后,让我们添加函数来处理切换细节和外部点击:
function toggleDetails(event: ToggleEvent) {
computedOpenState.value = event.newState === 'open'
}
onClickOutside(details, () => (computedOpenState.value = false))
现在,让我们向组件添加一些模板。首先,如果嵌套内容没有更多嵌套子项,我们只想显示一个带有摘要名称的段落:
<p v-if="!hasNestedChildren">
{{ summary }}
</p>
在其他情况下,我们想要利用 details
HTML 标签:
<p v-if="!hasNestedChildren">
{{ summary }}
</p>
<details
v-else
:open="computedOpenState"
:name="summary"
ref="details"
@toggle="toggleDetails"
>
...
</details>
在 details
标签内,我们要添加以下代码来处理显示摘要和嵌套节点树:
<summary>
{{ summary }}
</summary>
<template v-if="hasNestedChildren">
<NodeTree
v-for="(child, key) in content.children"
:key
:summary="child.summary"
:content="child"
@click="toggleChildren"
/>
</template>
下面,您可以看到该组件的完整代码:
<script setup lang="ts">
import { onClickOutside } from '@vueuse/core'
import { computed, ref } from 'vue'
const props = defineProps({
summary: {
type: String,
default: 'disclosure'
},
open: {
type: Boolean,
default: false
},
content: {
type: Object,
default: () => ({})
}
})
const computedOpenState = ref(props.open)
const details = ref(null)
const hasNestedChildren = computed(() => props.content.children?.length)
function toggleDetails(event: ToggleEvent) {
computedOpenState.value = event.newState === 'open'
}
onClickOutside(details, () => (computedOpenState.value = false))
</script>
<template>
<p v-if="!hasNestedChildren">
{{ summary }}
</p>
<details
v-else
ref="details"
:open="computedOpenState"
:name="summary"
@toggle="toggleDetails"
>
<summary>
{{ summary }}
</summary>
<template v-if="hasNestedChildren">
<NodeTree
v-for="(child, key) in content.children"
:key
:summary="child.summary"
:content="child"
@click="toggleChildren"
/>
</template>
</details>
</template>
最后,该组件可以像下面这样使用:
<template>
<NodeTree v-if="data" :content="data" :summary="data.summary" />
</template>
就是这样!您拥有完全正常工作的递归节点树组件:)
总结
干得好!您刚刚学习了如何构建递归 Vue 组件。
保重,下次再见!
And happy coding as always 🖥️
评论区
评论加载中...