在 Vue.js 和 Vite 中动态内联导入原始 SVG

Say*_*yed 12 javascript vue.js vuejs3 vite

所以我尝试使用 Vite 上的内联导入将 SVG 作为字符串导入到我的 Vue 组件中,如下所示

<script>
const getSvgIcon = async (name) => {
  const module = await import(`../icons/${name}.svg?raw`)
  return module.default
}

export default {
  props: {
    name: String,
  },
  data() {
    return {
      svg: null,
    }
  },
  watch: {
    name: {
      async handler(name) {
        this.svg = await getSvgIcon(name)
      },
      immediate: true,
    },
  },
}
</script>

<template>
  <div v-html="svg"></div>
</template>
Run Code Online (Sandbox Code Playgroud)

这在模式下运行时效果很好npm run dev

然而,问题发生在运行时npm run build,我最终Error: Unknown variable dynamic import明显因为我使用了?raw后缀。

目前有解决方案吗?或者这是 Vite 的一个障碍吗?

rol*_*oli 20

正如 @tony19 评论的那样,这可能是一个错误。我打开了一个问题,您可以在此处关注。

作为使您的代码正常工作的解决方法,请按照以下步骤操作:

步骤1:

将所有 SVG 转换为 Vue 组件。这样,你才能有更好的管理。为此,您只需编辑文件名,将其替换为.svgto.vue并将内容包装在template标签内即可。

如果你想保留svg文件,你可以使用vite-svg-loader插件,这样你就可以做到:

import IconComponent from './my-icon.svg?component'

第2步:

创建一个 SVG 图标组件:

<script>
import { defineAsyncComponent } from 'vue';

export default {
  props: {
    name: {
      type: String,
      required: true,
    },
  },

  computed: {
    dynamicComponent() {
      const name = this.name;

      return defineAsyncComponent(() => import(`./icons/${name}.vue`));
    },
  },
};
</script>

<template>
  <component :is="dynamicComponent" />
</template>
Run Code Online (Sandbox Code Playgroud)

步骤3

现在您可以导入SvgIcon.vue并使用 SVG 图标的名称,如下所示:

<script>
import SvgIcon from './components/SvgIcon.vue'

export default {
  components: {
    SvgIcon
  }
}
</script>

<template>
  <SvgIcon name="user" />
</template>
Run Code Online (Sandbox Code Playgroud)

在 Stackblitz 上观看直播


如果您喜欢上述方法,我最近写了一篇关于它的文章:

使用 Vite、Vue 3、Quasar 和 Pinia 统一 SVG 图标


小智 9

看看我自己创建的这个例子。

<template>
    <i v-html="svg" />
</template>

<script lang="ts" setup>
    import { computed } from 'vue';

    const props = defineProps({
        icon: {
            type: String,
            required: true,
        },
        src: {
            type: String,
            default: '',
        },
    });
    const path = props.src ? props.src : '';
    const file = `${path}icon-${props.icon}`;
    const modules = import.meta.glob('../../assets/icons/**/*.svg', {
        as: 'raw',
        eager: true,
    });
    const svg = computed(() => {
        return modules['../../assets/icons/' + file + '.svg'] ?? modules['../../assets/icons/icon-logo-cone.svg'];
    });
</script>
Run Code Online (Sandbox Code Playgroud)

这就是在一个漂亮且简约的组件中动态加载 SVG 所需的全部内容。

啊,不要忘记,您还可以使用纯 css 更改 svg 的颜色。

用法:

<UiIcon
    class="w-4 text-gray-600"
    icon="search"
/>
Run Code Online (Sandbox Code Playgroud)

  • 最后一个不需要插件的内部解决方案,谢谢!不过,它可能可以进行一些优化,每次调用该组件时,我们都会全局访问整个文件夹。也许值得只执行一次并存储图标列表 (3认同)