一、使用普通的component组件方式
-
如果是使用setup语法糖制作的组件则需要通过插件配置组件的 name 属性
yarn add vite-plugin-vue-setup-extend -D
如果是非setup语法糖制作的组件或者为vue2中的组件时,则必须声明组件的name属性,以便让vue工程识别
export default defineComponent({ name: 'defaultRenderComponent' })
-
定义组件的内容
<template>
<div v-for="(item, index) in props.list"
:key="index"
>
<div class="left">
{{item.name}}
</div>
<div class="right" v-if="item.children"
style="margin-left: 40px;"
>
<default-render :list="item.children" :parent-key="parentKey? (parentKey + ':' + index) : index"></default-render>
</div>
</div>
</template>
<script setup lang="ts" name="defaultRenderComponent">
interface ListItemType {
name: string,
children?: Array<ListItemType>
}
interface PropType {
list: ListItemType[],
parentKey?: string
}
const props = withDefaults(defineProps<PropType>(), {
})
</script>
<style scoped lang="scss">
</style>
二、jsx或tsx形式的组件
本质上还是需要有组件的 name 属性值使得vue工程识别,不过在于代码tsx/jsx易读性比较强。
- 加入jsx编译插件
npm install @vitejs/plugin-vue-jsx -D
- 在vite.config.ts中加入
import vueJsx from '@vitejs/plugin-vue-jsx'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
vueJsx()
],
})
- 在项目中创建 tsxRender.tsx 文件
import {defineComponent} from "vue";
interface ListItemType {
name: string,
children?: Array<ListItemType>
}
interface PropType {
list: ListItemType[],
parentKey?: string
}
export default defineComponent({
name: 'tsxRenderComponent',
props: {
list: {
type: Array<ListItemType>,
default: () => ([])
},
parentKey: {
type: String,
default: ''
}
},
setup(props: PropType, emits: any) {
const {list, parentKey} = props;
console.log("list: ", list)
return () => (
<>
{
list.map((item, index) => {
return (
<div style={parentKey? 'margin-left: 40px;' : ''}>
<div class="left">
{item.name}
</div>
{
item.children? <tsxRenderComponent list={item.children}
parentKey={parentKey? (parentKey + ':' + index) : index}>
</tsxRenderComponent> : ''
}
</div>
)
})
}
</>
)
}
})
三、使用所创建的递归组件
<template>
<defaulRender :list="data"/>
<div>分割线</div>
<tsx-render-component :list="data"/>
</template>
<script lang="ts" setup>
import defaultRender from "@/components/recursionComponent/defaultRender.vue";
import TsxRenderComponent from "@/components/recursionComponent/tsxRender.tsx";
const data = [
{
id: 1,
name: '第1阶梯',
},
{
id: 2,
name: '第2阶梯',
children: [
{
id: 21,
name: '第2-1阶梯',
},
{
id: 22,
name: '第2-2阶梯',
},
]
},
{
id: 3,
name: '第3阶梯',
children: [
{
id: 31,
name: '第3-1阶梯',
children: [
{
id: 311,
name: '第3-1-1阶梯',
},
]
},
{
id: 32,
name: '第3-2阶梯',
children: [
{
id: 321,
name: '第3-2-1阶梯',
children: [
{
id: 3211,
name: '第3-2-1-1阶梯',
},
]
},
]
},
]
},
]
</script>