vue@2 使用 svg-icon:webpack + svg-sprite-loader

项目结构

$ tree -I node_modules
.
├── README.md
├── package.json
├── pnpm-lock.yaml
├── public
│ ├── index.html
│ └── libs
│ └── vue@2.6.14.min.js
├── src
│ ├── App.vue
│ ├── icons
│ │ ├── SvgIcon.vue
│ │ ├── index.js
│ │ └── svg
│ │ └── open.svg
│ └── main.js
└── webpack.config.js

依赖

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

webpack 配置

// webpack.config.js
const path = require('path');

module.exports = {
module: {
rules: [
// 处理svg图标
{
test: /\.svg$/,
include: [path.resolve('./src/icons/svg')],
use: [
{
loader: 'svg-sprite-loader',
options: {
symbolId: 'icon-[name]',
},
},
// 移除svg的fill属性
{
loader: 'svgo-loader',
options: {
// 必须指定name!
plugins: [
{
name: 'removeAttrs',
params: { attrs: 'fill' },
},
],
},
},
],
},
],
},
};

定义 Vue 组件


<template>
<svg class="svg-icon" aria-hidden="true">
<use :xlink:href="iconName">use>
svg>
template>

<script>
// svg 组件
export default {
name: 'svg-icon',

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

computed: {
iconName() {
return `#icon-${this.name}`;
},
},
};
script>

<style lang="less">
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
style>
// src/icons/index.js
import SvgIcon from './SvgIcon.vue'; // svg component

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

requireAll(req);

// register globally
export default {
install(Vue) {
Vue.component('svg-icon', SvgIcon);
},
};

全局注册

import Vue from 'vue';
import SvgIcon from './icons/index.js';

Vue.use(SvgIcon);

使用 icon

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

完整代码:​​https://github.com/mouday/vue2-svg-demo​

在线 demo: ​​https://mouday.github.io/vue2-svg-demo/dist/​

参考:

  • 【vue】webpack 插件 svg-sprite-loader—实现自己的 icon 组件
  • 手摸手,带你优雅的使用 icon
  • 使用 svg-sprite-loader、svgo-loader 优化 svg symbols