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

How to define components with "require.context" in "<script setup>"?

如何使用 require.context 添加组件? script setup shows this 示例的 rfc。在示例中,必须导入每个组件。

在选项 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>