svg-sprite-loader实现icon组件

1,765 阅读2分钟

一、前言

以前引入icon图片,每次都需要指定src路径。而通过svg-sprite-loader可以在组件上写个文件名就可以引入图片了。实现icon组件涉及到的知识点如下:
1.svg-sprite-loader
首先了解一下svg-sprite-loader是什么?svg-sprite-loader是一种创建雪碧图的webpackloader,它的优点主要有两点:

  • 大多数选项是自动配置的
  • 精灵会自动呈现并注入页面中,您只需通过引用图像即可。
    <svg><use xlink:href="#id"></use></svg>
    

2.vuecli环境下的webpack配置

二、vueCli配置webpack相关

  • 简单的配置方式
    调整 webpack 配置最简单的方式就是在 vue.config.js 中的 configureWebpack 选项提供一个对象:
    // vue.config.js
        module.exports = {
          configureWebpack: {
            plugins: [
              new MyAwesomeWebpackPlugin()
            ]
          }
        }
    
  • 链式操作 (高级)
    webpack-chain可以定义具名的 loader 规则和具名插件,允许更细粒度地去配置。配置时使用vue inspect审查配置很方便。 通过config可以访问到module、plugin等选项,然后进入里面修改rules等配置,返回使用.end()。
    chainWebpack:config=>{
        config.module
        .rule('svg')
        .exclude.add(resolve('src/icons'));
        config.module
        .rule('icons')
        .test(/\.svg$/)
        .include.add(resolve('src/icons'))
        .end()
        .use('svg-sprite-loader')
            .loader('svg-sprite-loader')
            .options({symbolId:'icon-[name]'})
    }
  • vue inspect审查配置
    该命令会将解析出来的 webpack 配置、包括链式访问规则和插件的提示打印到 stdout。
    • 将其输出重定向到一个文件以便进行查阅
    vue inspect > output.js
    
    • 可以通过指定一个路径来审查配置的一小部分
    vue inspect module.rules.0
    
    • 指向一个规则或插件的名字
    vue inspect --rule vue
    vue inspect --plugin html
    
    • 最后,你可以列出所有规则和插件的名字
    vue inspect --rules
    vue inspect --plugins
    
  • require.context
    每次还要import svg文件,也很繁琐,为了达到更简洁的目的。可以使用webpack的require.contextAPI来动态引入icon文件夹虾的svg图片。
    require.context允许您传递要搜索的目录,指示是否也应搜索子目录的标志以及用于匹配文件的正则表达式。
    require.context('./test', false, /\.test\.js$/);
    // a context with files from the test directory that can be required with a request endings with `.test.js`.
    //在./test中找可能以.test.js结束的文件。

require.context会返回一个函数,并且该函数有keys(),id, resolve() 属性。 keys()方法返回的该模块可以处理的所有可能请求的模块的数组,简单一点就是满足该参数的模块;resolve()返回的是请求的module的id;id是该context module的id;

三、svg-sprite-loader的原理以及如何使用?

SVG Sprite最佳实践是使用symbol元素。而symbol是svg的元件,集合了三个svg图标的svg的元素会这样:

<svg>
    <symbol>
        <!-- 第1个图标路径形状之类代码 -->
    </symbol>
    <symbol>
        <!-- 第2个图标路径形状之类代码 -->
    </symbol>
    <symbol>
        <!-- 第3个图标路径形状之类代码 -->
    </symbol>
</svg>

接下来要使用use才能显示,use元素非常强大,可以跨svg使用,也就是可以调用其他svg文件的元素。

<svg>
    <use xlink:href="#symbolId"></use>
</svg>

因此可以分析出,svg-sprite-loader的原理就是:icon文件夹下的每个icon都对应着一个symbol,利用use指定相应的symbolId引入使用。

四、代码具体实现

  • 新建icon文件夹,复制svg的代码
  • vue.config.js配置
    将原本的svg的rules,去除我们新建的icon目录,不使用以前的loader,然后针对当前目录的svg设置新的svg-sprite-loader。
const path = require('path')
function resolve(dir){
    return path.join(__dirname,dir);
}
module.exports = {
    chainWebpack:config=>{
        config.module
        .rule('svg')
        .exclude.add(resolve('src/icons'));
        config.module
        .rule('icons')
        .test(/\.svg$/)
        .include.add(resolve('src/icons'))
        .end()
        .use('svg-sprite-loader')
            .loader('svg-sprite-loader')
            .options({symbolId:'icon-[name]'})
    }
}
  • 自动引入svg文件
    在icon文件夹下新建index.js
    import Vue from 'vue'
    import myicon from '../components/myicon'
    const req = require.context("./svg", false, /\.svg$/);
    //这里还是不太明白
    req.keys().map(req)
    Vue.component("myicon", myicon)
  • icon组件
    <template>
      <div>
          <svg>
              <use :xlink:href="iconName"></use>
          </svg>
      </div>
    </template>
    <script>
    export default {
        name:'myicon',
        props:['name'],
        computed:{
            iconName(){
                return '#icon-'+this.name
            }
        }
    
    }
    </script>
    
    <style>
    </style>