vue3中实现递归组件的两种用法 - 多级评论的使用场景

一、使用普通的component组件方式

  1. 如果是使用setup语法糖制作的组件则需要通过插件配置组件的 name 属性

    yarn add vite-plugin-vue-setup-extend -D
    

    如果是非setup语法糖制作的组件或者为vue2中的组件时,则必须声明组件的name属性,以便让vue工程识别

    export default defineComponent({
    	name: 'defaultRenderComponent'
    })
    
  2. 定义组件的内容

<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易读性比较强。

  1. 加入jsx编译插件
npm install @vitejs/plugin-vue-jsx -D
  1. 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()
  ],
})
  1. 在项目中创建 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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值