Skip to content

在项目中我们除了使用UI框架自带的图标库之外,还会使用额外的图标,对于这些自定义图标,我们该如何展示这些图标呢?

判断是否为外部图标

创建校验文件:src/utils/validate.js

javascript
/**
 * 判断是否为外部资源 true代表是外部资源
 * @param path 资源路径
 */
export function isExternal(path) {
  return /^(https?:|mailto:|tel:)/.test(path)
}

创建展示SVG图标组件

文件名称及路径:src/components/SvgIcon/index.vue

vue
<template>
  <!-- 展示外部图标 -->
  <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" :class="className" />
  <!-- 展示内部图标 -->
  <svg v-else class="svg-icon" :class="className" aria-hidden="true">
    <use :xlink:href="iconName" />
  </svg>
</template>

<script setup>
import { isExternal as external } from "@/utils/validate"
import { computed, defineProps } from "vue"

const props = defineProps({
  icon: {
    type: String,
    required: true
  },
  className: {
    type: String,
    default: ""
  }
})

// 判断当前图标是否为外部图标
const isExternal = computed(() => external(props.icon))
// 外部图标样式
const styleExternalIcon = computed(() => ({
  mask: `url(${props.icon}) no-repeat 50% 50%`,
  "-webkit-mask": `url(${props.icon}) no-repeat 50% 50%`
}))
// 内部图标样式
const iconName = computed(() => `#icon-${props.icon}`)
</script>

<style scoped>
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}

.svg-external-icon {
  background-color: currentColor;
  mask-size: cover !important;
  display: inline-block;
}
</style>

使用远程svg图标

vue
<template>
  <div class="login-container">
    <svg-icon icon="https://res.lgdsunday.club/user.svg" class-name="svg-icon"></svg-icon>
  </div>
</template>
<script setup>
import SvgIcon from '@/components/SvgIcon/index.vue'
</script>

导入内部SVG图标

  1. 导入svg图标,文件结构大致如下

    markdown
    src
     -icons
      -svg
       -article.svg
       -article-ranking.svg
       -change-theme.svg
       -eye.svg
       -hamburger-closed.svg
       -……
  2. 安装插件

    shell
    npm i vite-plugin-svg-icons -D
  3. vite.config.ts

    javascript
    import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
    import path from 'path'
    
    export default defineConfig({
      plugins: [
        createSvgIconsPlugin({
          // 指定需要缓存的图标文件夹
          iconDirs: [path.resolve(process.cwd(), 'src/icons/svg')],
          // 指定symbolId格式
          symbolId: 'icon-[dir]-[name]',
        })
      ]
    })
  4. main.js引入插件

    javascript
    import "virtual:svg-icons-register"
  5. 使用,icon就是svg文件的名字

    vue
    <template>
       <svg-icon icon="password" class-name="svg-icon"></svg-icon>
    </template>
    <script setup>
    import SvgIcon from '@/components/SvgIcon/index.vue'
    </script>

SvgIcon组件全局注册

如果您的项目大量使用svg图标,不想每次使用都重新引入,那么可以使用全局注册的方式,在main.js中进行注册

javascript
import { createApp } from "vue"
import App from "./App.vue"
import svgIcon from "@/components/SvgIcon/index.vue"

const app = createApp(App)
app.component("svgIcon", svgIcon)
app.mount("#app")