SVG雪碧图 svg-sprite-loader

1,717 阅读1分钟

通常引用多个svg图标

<li><img src="@/icons/home.svg" /></li>
<li><img src="@/icons/list.svg" /></li>
<li><img src="@/icons/settings.svg" /></li>

为了方便组件化管理,可以使用svg雪碧图方式引用,组件化后效果为:

<IconHome>
<IconList>
<IconSettings>

除了组件化的好处外,通常以图片形式引入的svg对样式是不可编辑的,但svg类型引入可以操作svg的颜色和大小,实现原理是利用svg的symbol,通过svg-sprite-loader将指定目录下的svg图标转为以下格式:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <symbol class="icon" viewBox="0 0 1024 1024" id="home">...icon path...</symbol>
    <symbol class="icon" viewBox="0 0 1024 1024" id="list">...icon path...</symbol>
    <symbol class="icon" viewBox="0 0 1024 1024" id="settings">...icon path...</symbol>
</svg>

然后html中通过下面的方法调用:

<svg aria-hidden="true">
  <use xlink:href="#home"></use>
</svg>

详细原理参考:www.zhangxinxu.com/wordpress/2…

1. 安装

npm install --save svg-sprite-loader

2. webpack配置

  • vue-cli中的vue.config.js配置

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

    module.exports = {  
      ...  
      module: {
        rules: [
          {
            test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
            loader: 'url-loader',
            exclude: [resolve('src/icons')], // 除icon以外的其他svg文件处理
            options: {
              limit: 10000,
              name: utils.assetsPath('img/[name].[hash:7].[ext]')
            }
          },
          // svg-sprite-loader svg icon
          {
            test: /\.svg$/,
            loader: 'svg-sprite-loader',
            include: [resolve('src/icons')],
            options: {
              symbolId: 'icon-[name]',
            }
          }
        ] 
      }
      ...
    }
    

3. 创建svg图标通用组件/components/svgIcon.vue

<template>
  <svg aria-hidden="true">
    <use :xlink:href="iconName" />
  </svg>
</template>
<script>
export default {
  name: 'SvgIcon',
  props: {
    iconClass: {
      type: String,
      required: true,
    }
  },
  computed: {
    iconName() {
      return `#icon-${this.iconClass}`;
    }
  },
};
</script>

4. 引入全局SvgIcon

import Vue from 'vue';
import SvgIcon from '@/components/svgIcon';// svg component
// register 
globallyVue.component('SvgIcon', SvgIcon);
const req = require.context('./svg', false, /\.svg$/);
const requireAll = requireContext => requireContext.keys().map(requireContext);
requireAll(req);

5. 创建图标组件,例如home图标/components/icons/home

<template>
  <SvgIcon    class="icon"    icon-class="home"  />
</template>

6. 最终引用图标

<template>
  <div class="wrapper">
    <IconHome />
    <IconList />
    <IconSettings />
  </div>
</template>
<script>
import IconHome from '@/components/icons/home';
import IconList from '@/components/icons/list';
import IconSettings from '@/components/icons/settings';
export default {  
  name: 'Toolbar',  
  components: { IconHome, IconList, IconSettings}
};
</script>