vue中使用svg-sprite-loader处理svg图片

网上已经有很多文章写了相似的例子,不过自己实践之后还是把过程记录下来,这样知识就是自己的了。

版本:@vue/cli 4.4.1

实现内容:1.vue载入svg 2.能够更改svg样式 3.svg无限旋转

1.使用的loader:svg-sprite-loader、svgo-loader

我们在vue.config.js文件里找到chainWebpack属性,添加如下代码:

chainWebpack: config => {
    // ......
    config.module
        .rule('svg')
        .exclude.add(resolve('src/assets/icons/svg'))
        .end();
    config.module
        .rule('icons')
        .test(/\.svg$/)
        .include.add(resolve('src/assets/icons/svg'))
        .end()
        .use('svg-sprite-loader')
        .loader('svg-sprite-loader')
        .options({
            symbolId: 'icon-[name]',
        })
        .end();
    // .......

2.需要安装的loader:svg-sprite-loader、svgo-loader

npm i svg-sprite-loader svgo-loader -D

3.引入svg图片

我们在src/assets下新建icons文件夹,文件夹里再新建svg文件夹,将svg图片放至svg文件夹里。(具体路径可根据自己习惯配置)

4.统一引入svg图片

在src下新建icons文件夹,新建index.js文件(要注意路径的配置):

const req = require.context('@/assets/icons/svg/', false, /\.svg$/);
const requireAll = requireContext => requireContext.keys().map(requireContext);
requireAll(req);

5.在main.js中引入

import './icons';

6.在组件中使用


<svg>
    <use xlink:href="#icon-XXX">use>
svg>

这样,我们就能在界面上看到svg图片了。

7.优化

但是这样子使用有点麻烦,我们希望能够像那些ui组件库一样,直接XX-icon标签就能使用,所以我们可以自定义一个组件.
在components文件夹下新建SvgIcon.vue文件:

<template>
    
    <svg :class="svgClass" aria-hidden="true" v-on="$listeners">
        <use :xlink:href="iconName"/>
    svg>
template>
 
<script>
export default {
    name: 'SvgIcon',
    props: {
        name: {
            type: String,
            required: true
        },
        className: {
            type: String,
            default: ''
        }
    },
    computed: {
        iconName() {
            return `#icon-${this.name}`;
        },
        svgClass() {
            if (this.className) {
                return 'scoped-svg-icon ' + this.className;
            } else {
                return 'scoped-svg-icon';
            }
        }
    }
};
script>
 
<style lang="less">
  .scoped-svg-icon {
    width: 1em;
    height: 1em;
    vertical-align: -0.15em;
    fill: currentColor;
    overflow: hidden;
  }
style>

然后我们在icons的index.js文件下引入icon组件:

import Vue from 'vue';
import SvgIcon from '@/components/SvgIcon';

Vue.component('svg-icon', SvgIcon);
 
const req = require.context('@/assets/icons/svg/', false, /\.svg$/);
const requireAll = requireContext => requireContext.keys().map(requireContext);
requireAll(req);

最后大功告成,在界面中使用:

<svg-icon name="copy">svg-icon>

8.继续优化

使用的时候发现,有时候我们无法修改svg图片的颜色,比如在icon-font网站上下载的svg图片颜色无法更改。此时我们需要删掉svg原有的path中的fill属性:

修改vue.config.js为如下代码:

chainWebpack: config => {
    // ......
    config.module
        .rule('svg')
        .exclude.add(resolve('src/assets/icons/svg'))
        .end();
    config.module
        .rule('icons')
        .test(/\.svg$/)
        .include.add(resolve('src/assets/icons/svg'))
        .end()
        .use('svg-sprite-loader')
        .loader('svg-sprite-loader')
        .options({
            symbolId: 'icon-[name]',
        })
        .end()
        .before('svg-sprite-loader')
        .use('svgo-loader')
        .loader('svgo-loader')
        .options({
            plugins: [
                {removeAttrs: {attrs: 'path:fill'}}
            ]
        })
        .end();
    // .......

此时再去修改svg颜色,就能生效了。

它会去掉svg原有的颜色,默认为黑色。

9.添加功能

添加一个加载的动画图标功能,当传入spin属性为true时,我们就让图标无限旋转起来。修改SvgIcon.vue组件为:

<template>
    
    <svg :class="`${svgClass} ${spin ? 'scoped-svg-animation' : ''}`" aria-hidden="true" v-on="$listeners">
        <use :xlink:href="iconName"/>
    svg>
template>
 
<script>
export default {
    name: 'SvgIcon',
    props: {
        name: {
            type: String,
            required: true
        },
        className: {
            type: String,
            default: ''
        },
        // 是否旋转
        spin: {
            type: Boolean,
            default: false
        }
    },
    computed: {
        iconName() {
            return `#icon-${this.name}`;
        },
        svgClass() {
            if (this.className) {
                return 'scoped-svg-icon ' + this.className;
            } else {
                return 'scoped-svg-icon';
            }
        }
    }
};
script>
 
<style lang="less">
  .scoped-svg-icon {
    width: 1em;
    height: 1em;
    vertical-align: -0.15em;
    fill: currentColor;
    overflow: hidden;
    &.scoped-svg-animation {
        animation: rotate 2s linear infinite;
    }
    @keyframes rotate {
        from{transform: rotate(0deg)}
        to{transform: rotate(360deg)}
    }
  }

style>

至此一个小功能完成。

局限性:
1.当svg为色彩丰富的图标时,颜色达不到想要的效果
2.会清除掉原有的svg图颜色样式,不太友好

你可能感兴趣的:(vue,vue,svg,loader)