Skip to content

全局组件,递归组件

全局组件

需要再main.ts中去引入,引入之后就可以直接在vue文件中使用了,在main.ts中引入:

ts
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import card from './recursionCard.vue'

export const app = createApp(App)

app.component('card',card)

app.mount('#app')

需要批量注册全局组件,可以参考element plus的icon图标组件的批量引入方式:

ts
// main.ts

// 如果您正在使用CDN引入,请删除下面一行。
import * as ElementPlusIconsVue from '@element-plus/icons-vue'

const app = createApp(App)

//进行批量全局注册
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

递归组件

展开
vue
<template>
    <div class="card">
        <header>
            <div>
                标题
            </div>
            <div>
                副标题
            </div>
        </header>
        <section>
            <div>
                内容
                <recursionInput :data="data"></recursionInput>
            </div>
        </section>
    </div>
</template>

<script setup lang='ts'>
import { ref, reactive } from 'vue'
import recursionInput from './recursionInput.vue'
interface cardType {
    index: string,
    checked: boolean,
    children?: cardType[]
}

const data = reactive<cardType[]>([
    {
        index: '1-1',
        checked: false,
        children: [
            {
                index: '1-1-1',
                checked: false,
            },
            {
                index: '1-1-2',
                checked: false,
            },
        ]
    },
    {
        index: '1-2',
        checked: false,
    },
    {
        index: '1-3',
        checked: false,
        children: [
            {
                index: '1-3-1',
                checked: false,
            },
            {
                index: '1-3-2',
                checked: false,
                children: [
                    {
                        index: '1-3-2-1',
                        checked: false,
                    },
                    {
                        index: '1-3-2-2',
                        checked: false,
                    },
                ]
            },
        ]
    },
    {
        index: '1-4',
        checked: false,
    },
])

</script>
<style lang="less" scoped>
@border: #000;

.card {
    border: 1px solid @border;
    width: 400px;

    header {
        display: flex;
        justify-content: space-between;
        padding: 5px;
        border-bottom: 1px solid @border;
    }

    section {
        padding: 5px;
        min-height: 300px;
    }
}
</style>
vue
<template>
    <div class="inputStyle">
        <!-- 需要用.stop阻止冒泡事件 -->
        <div @click.stop="clickInput(cardData, $event)" v-for="cardData in data">
            <input v-model="cardData.checked" type="checkbox"><span>{{ cardData.index }}</span>
            <rarrot style="margin-left: 10px;" v-if="cardData?.children?.length" :data="cardData.children">
            </rarrot>
        </div>
    </div>
</template>

<script setup lang='ts'>
import { ref } from 'vue'
interface cardType {
    index: string,
    checked: boolean,
    children?: cardType[]
}

defineProps<{
    data?: cardType[]
}>()

// 如果需要修改递归组件的名,可以使用以下方式:
defineOptions({
    name: 'rarrot'
})

const clickInput = (cardData: cardType, e: { target: any; }) => {
    console.log("🚀  cardData", cardData, e.target)
}
</script>

<style lang="less" scoped>
.inputStyle {
    border: none
}
</style>
标题
副标题
内容
1-1
1-1-1
1-1-2
1-2
1-3
1-3-1
1-3-2
1-3-2-1
1-3-2-2
1-4

Released under the MIT License.