Vite+Vue3封装SvgIcons组件(不借助第三方插件)

61 阅读1分钟
  • 关键知识点

    • 使用 await import(`@/assets/icons/${props.name}.svg`) 来导入对应资源,并对得到的资源使用 decodeURIComponent 解码
    • 如果使用组件时属性失效(如大小、颜色),可能是SVG文件本身属性问题,文末有修改帮助
  • 具体步骤

    1. 下载相应SVG资源放在对应文件夹下 assets/icons/multi-language.svg
    2. 编写组件 components/SvgIcon/index.vue
    // vue3风格 封装组件接近Element-plus风格
    <script setup>
    import { ref, computed, watch } from 'vue'
    const props = defineProps({
      name: {
        type: String,
        required: true
      },
      color: {
        type: String
      },
      size: {
        type: [Number, String]
      },
      spin: {
        type: Boolean,
        default: false
      },
    })
    // 获取SVG文件内容
    const svgContent = ref(null)
    const loadSvg = async () => {
      try {
        const response = await import(`@/assets/icons/${props.name}.svg`)
        // 导入进来的图标是URL编码的形式,且只需取,后的部分
        svgContent.value = decodeURIComponent(response.default.split(',')[1])
      } catch(error) {
        console.error(`获取 ${props.name} 对应图标失败`, error)
        const errorIcons = await import(`@/assets/icons/error.svg`)
        svgContent.value = decodeURIComponent(errorIcons.default.split(',')[1])
      }
    }
    // 组件属性优先级最高,使用内联样式
    const getStyle = computed(() => {
      const { size, color } = props
      const style = {}
      if(size) style.fontSize = `${(''+size).replace('px', '')}px`
      if(color) style.color = color
      return style
    })
    // 修改name属性重新加载文件内容
    watch(() => props.name, loadSvg, { immediate: true })
    </script>
    
    <template>
      <i v-if="svgContent" :class="['el-icon', spin && 'svg-icon-spin']" :style="getStyle">
        <svg aria-hidden="true" v-html="svgContent">
        </svg>
      </i>
    </template>
    
    <style scoped>
    .el-icon {
      --color: inherit;
      position: relative;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 1em;
      height: 1em;
      font-size: inherit;
      line-height: 1em;
      color: var(--color);
      fill: currentColor;
    }
    
    .el-icon svg {
      width: 1em;
      height: 1em;
    }
    
    .svg-icon-spin {
      animation: circle 1.5s infinite linear;
    }
    
    /* 旋转动画 */
    @keyframes circle {
      0% {
        transform: rotate(0);
      }
    
      100% {
        transform: rotate(360deg);
      }
    }
    </style>
    
    1. 使用
    // 组件全局注册或导入 如果size、color属性失效,可能是SVG文件本身问题,见下文修改帮助
    <SvgIcon name="multi-language" :size="22" color="red"/>
    

    注意如果SVG文件本身有属性要进行修改

    1. 在VSCODE中打开SVG文件,如果默认是预览打开,右键选择打开方式然后用文本编辑器

      image.png

      image.png

    2. 文件内容丑化过的话直接格式化然后找到width、height属性删除,fill属性修改为currentColor image.png image.png