问题描述
如何使用 require.context 添加组件? script setup 的 rfc 显示了 this 示例。在示例中,每个组件都必须导入。
在选项 API 中,我使用此代码从特定文件夹中收集所有组件:
function getComponents() {
const context = require.context('../icons',true,/Icon[A-Z]\w+\.vue$/)
const res = {
components: {},namesForValidator: [],}
for (const key of context.keys()) {
const match = key.match(/\/(\w+)\.\w+$/)
if (match && match[1]) {
const name = kebabCase(match[1])
res.components[name] = context(key).default
res.namesForValidator.push(name)
}
}
return res
}
然后我将生成的组件对象添加到传递给 defineComponent 的选项对象中。
const { components,namesForValidator } = getIconsComponents()
export default defineComponent({
components,// ...
})
所有这些工作正常。 但是我不清楚如何使它工作。 也许有(或正在计划)一些未公开的 defineComponets 编译器宏可以解决这个问题?
解决方法
用下面的代码解决了这个问题。
<template>
<component :is="icon" />
</template>
<script lang="ts" setup>
import { kebabCase } from '@/helpers'
import { computed,toRefs } from 'vue'
import type { DefineComponent } from 'vue'
export interface IconComponentsList {
components: Record<string,DefineComponent>
}
function getIconsComponents(): IconComponentsList {
const context = require.context('../icons',true,/Icon[A-Z]\w+\.vue$/)
const res = {
components: {} as Record<string,DefineComponent>,}
for (const key of context.keys()) {
const match = key.match(/\/(\w+)\.\w+$/)
if (match && match[1] && typeof match[1] === 'string') {
const name = kebabCase(match[1].replace('Icon',''))
res.components[name] = context(key).default
}
}
return res
}
const { components }: IconComponentsList = getIconsComponents()
const { name } = toRefs(defineProps({
name: {
type: String,required: true,},}))
const icon = computed(() => {
return components[name]
})
</script>