vue3 封装公共svg组件

284 阅读1分钟

1.安装svg-sprite-loader插件

npm i svg-sprite-loader

2.vue.config.js中配置下

const { defineConfig } = require('@vue/cli-service');
const path = require('path');

function resolve(dir) {
  return path.join(__dirname, dir)
}

module.exports = defineConfig({
  transpileDependencies: true,
  publicPath: './',
  chainWebpack(config) {
    globalSass(config)
    globalSvg(config)
  }
})

/**
 * 注意Dependencies需要引入
 * "sass": "^1.32.7",
 *"sass-loader": "^12.0.0",
 *"sass-resources-loader": "^2.2.5"
 * @param config  chainWebpack(config) 中来的一个配置
 */
const globalSass = config => {
  const oneOfsMap = config.module.rule('scss').oneOfs.store
  oneOfsMap.forEach((item) => {
    item
      .use('sass-resources-loader')
      .loader('sass-resources-loader')
      .options({
        resources: './src/utils/mixin.scss'  //相对路径
      })
      .end()
  })
}

/**
 * 配置svg
 * @param {*} config 
 */
const globalSvg = config => {
  config.module.rule('svg')
    .exclude.add(resolve('src/icons'));
  //添加svg-sprite-loader
  config.module.rule('icons')
    .test(/\.svg$/) //设置test
    .include.add(resolve('src/icons')) //加入include
    .end()  //add完上下文进入数组,使用end回退
    .use('svg-sprite-loader')  //添加loader
    .loader('svg-sprite-loader')   //切换上下文到loader
    .options({ symbolId: 'icon-[name]' })
    .end()
}

3.在src目录下新建icons 目录 如图

image.png

svg目录用来存放svg文件

index.js

//图标自动导入
//利用webpack 的require.context自动导入
//返回的req是只去加载svg目录中的模块的函数
const req = require.context('./svg',false,/\.svg$/);
req.keys().map(req);

4.src/components下新建svgIcon.vue

<template>
    <svg :class="svgClass" aria-hidden="true" :style="`color:${color}`">
        <use :xlink:href="iconName"></use>
    </svg>
</template>
  
<script setup>
import { computed } from 'vue'
const props = defineProps({
    iconClass: {
        type: String,
        required: () => true,
    },
    className: {
        type: String,
        default: () => ''
    },
    color: {
        type: String,
        default: () => ''
    }
})

const iconName = computed(() => {
    return `#icon-${props.iconClass}`
})

const svgClass = computed(() => {
    return `svg-icon ${props.className}`
})
</script>
  
<style scoped>
.svg-icon {
    width: 1em;
    height: 1em;
    vertical-align: -0.15em;
    fill: currentColor;
    overflow: hidden;
    color: #2c2c2c;
}
</style>

5.将svgIcon 在main.js中实例化为全局组件

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import 'reset-css';
import 'amfe-flexible';
import './icons/index'
import svgIcon from './components/svgIcon.vue'

const app = createApp(App);
app.use(store);
app.use(router);
app.component('svgIcon', svgIcon)
app.mount('#app')

6.使用 如果class-name 中设置color 或者 color=“pink” 未生效,请在svg文件中删除fill属性

image.png

image.png