前端页面svg优化webpack+svg-sprite-loader+vue(二)

2,798 阅读2分钟

衔接上一篇文章,这一篇继续写我在那个项目的优化,大图的svg我通过了img src引入了项目,可是还有很多小的svg图标需要引入,如果在用img 引入 过多的网络请求造成不不必要的浪费,于是我有又开始作死了

svg-sprite-loader

因为我这个项目是 自己搭建的 webpack 使用的是vue框架,所以我很自然的想到 svg-sprite-loader 这个svg处理的神器,配置超级简单,基本度娘都有标准的写法,什么?还让我去百度,那我看你干嘛。 好吧兄弟们,好不多说看代码,我们只需要在 rules 中加入这个配置

 {
        test: /\.svg$/,
        loader: 'svg-sprite-loader',
        include:[path.resolve('src/asset/svgSprite')],
        options:{
            symbolId:'icon-[name]'
        }
}

现在我给大家解释下每个的意思

path.resolve('src/asset/svgSprite') // 需要处理svg存放的目录,这个目录和我大图svg是分开的哦~
symbolId:'icon-[name]' 就是我们合并之后svg文件子类的id名称

下面给大家看下项目run 之后的截图就了解了

红色箭头所指就是我svg文件名 icon 是后来追加上去的 等等先别走,还有一点就完事了,你要关掉了后面的内容咋看。注意如果项目中还用了 url-loader 那么还需要加一段代码

{
    test: /\.(png|jpg|gif|webp|woff|eot|ttf|svg)$/,
    use:{
        loader:'url-loader',
        options:{
            name:'img/[name].[ext]',
            limit:3000
        }
    },
    exclude:[path.resolve('src/asset/svgSprite')] // 这里是需要加的,意思是不处理这个文件
   
},

这样webpack的配置文件就修改完成了 接下来在 components 里面创建一个文件夹 例如我的文件名称是 svgIcon 里面创建两个文件 index.ts 和 svgIcon.vue 下面我放的是 vue+ts版的代码,如果大家项目没有用呢也不要灰心,我还会放一个普通版的

ts版

<template>
  <svg  :class="svgClass" 
        :style="{
            'width':`${width}rem`,
            'height':`${height}rem`
        }" 
        aria-hidden="true" >
    <use :xlink:href="iconName" ref="svgRefs"></use>
  </svg>
</template>
<script lang="ts">
import Vue from 'vue';
import { Component, Prop} from 'vue-property-decorator'; 
@Component
export default class svgIcon extends Vue { 
    name:string =  'svg-icon'
    @Prop(String) iconClass ;
    @Prop(String) className ;
    @Prop(Number) width ;
    @Prop(Number) height ;
    get iconName():string {
        return `#icon-${this.iconClass}`
    }
    get svgClass(): string{
        if (this.className) {
            return 'svg-icon ' + this.className
        } else {
            return 'svg-icon'
        }
    }  
}
</script>

<style scoped>
.svg-icon {  
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}
</style>

普通版

svgIcon.vue

<template>
  <svg  :class="svgClass" 
        :style="{
            'width':`${width}rem`,
            'height':`${height}rem`
        }" 
        aria-hidden="true" >
    <use :xlink:href="iconName" ref="svgRefs"></use>
  </svg>
</template>
<script>
export default {
  name: 'svg-icon',
  props: {
    iconClass: {
      type: String,
      required: true
    },
    className: {
      type: String
    },
    width:{
        type:Number
    },
    height:{
        type:Number
    }
  },
  computed: {
    iconName() {
      return `#icon-${this.iconClass}`
    },
    svgClass() {
      if (this.className) {
        return 'svg-icon ' + this.className
      } else {
        return 'svg-icon'
      }
    }
  },
  mounted(){      
  } 
}
</script>

<style scoped>
.svg-icon {  
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}
</style>

最后是 index文件的内容

index.js
import Vue from 'vue'
import SvgIcon from './svgIcon.vue'
Vue.component('svg-icon',SvgIcon);

const requireAll = requireContext => 
{
    requireContext.keys().map(requireContext)
}

const req = require.context('./../../asset/svgSprite', false, /\.svg$/)
requireAll(req)

关于 require.context 是webpack导入文件的一种写法,只能在webpack项目中用 最后在 vue项目的入口文件中加一句话就ok啦

import './components/svgIcon'

最后给大家举个使用例子 因为我们是全局注册了所以用的时候只要像下面这样就可以啦

<svg-icon class="lls" icon-class="jingjingyeye" :width="4.46" :height="2.05"></svg-icon>

为啥这就可以了呢?我自问自答下,因为我们开始在webpack中的配置他把我们的svg全部注入到了我们index.html 的 body 中了。看完随手左侧小手下,有问题大家就留言。看到我会回复的。

使用这种方式的好处不言而喻,唯一值得注意的问题就是我们要注意svg的大小,如果文件太大就不要用了,毕竟这是把svg直接注入到index.html中的