如何在“<script setup>”中定义带有“require.context”的组件?

问题描述

如何使用 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>