vue工程使用svg图片,svg-sprite-loader缺陷,你们的按需加载svg是错误的。

起因

el-button组件只有icon属性标签,不支持单独的slot,但是项目中的svg图标都用《svg-icon》封装起来了。想着自己用css引入svg图标,然后一直不显示。结果发现,svg-sprite-loader导致了整个svg源文件加载到了css代码中。陷入沉思……

一、为什么大家都用svg-sprite-loader去处理svg加载

其实这是老做法了,我发现在新的浏览器版本中,或者不为了兼容ie的话,那么没必要啊。用mask就可以了。并且能做到一样的功能,使用了反而会导致我上面发生的问题。

二、正确的按需加载svg图标。请不要用require.content了。

require.content会导致所有使用该api导入的资源,会加入到loader中,影响初始加载速度

require.content会导致所有使用该api导入的资源,会加入到loader中,影响初始加载速度

require.content会导致所有使用该api导入的资源,会加入到loader中,影响初始加载速度

重要的事情说三遍,是所有使用该api都会导致该问题!!!

正确的做法是使用import去加载svg图标。

三、使用svg-sprite-loader的正确方式和按需加载

1、vue.config.js

const resolve = (dir) => path.join(__dirname, dir) // 读取文件

// const svgRule = config.module.rule('svg')
    // svgRule.uses.clear()
    // svgRule.use('svg-sprite-loader').loader('svg-sprite-loader').options({
    //   symbolId: 'icon-[name]',
    // })
复制代码

2、svg-icon源码,vue3示例,vue2同理

index.js部分定义按需加载svg图片

// import svgList from './svgList' // svg图片名称数组

// 按需导入svg图片
  /*svgList.forEach((name) => {
    import(`@/components/SvgIcon/svg/${name}.svg`)
  })*/

<template>
  <svg v-on="$attrs" class="svg-icon" aria-hidden="true">
    <use :xlink:href="`#icon-${name}`" />
  </svg>
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
  name: 'SvgIcon',
  props: {
    name: {
      type: String,
      default: 'assloss',
    },
  },
})
</script>
<style lang="scss" scoped>
// 实现样式控制变色
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}
</style>
复制代码

四、采用mask替代上述方式,也不需要配置svg-sprite-loader

1、html部分

<div :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />

styleExternalIcon() {
      return {
        mask: `url(${require(`@/components/SvgIcon/svg/${this.iconClass}.svg`)}) no-repeat 50% 50%`,
        '-webkit-mask': `url(${require(`@/components/SvgIcon/svg/${this.iconClass}.svg`)}) no-repeat 50% 50%`,
      }
    },
复制代码

2、css

.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}

.svg-external-icon {
  background-color: currentColor;
  mask-size: cover !important;
  display: inline-block;
}
复制代码

最后关于颜色和大小控制也完全可以做到用font-size和color控制。而且我也可以自己把图标再控制封装,然后放在el-button里面了。

五、总结

唉,早上发生的问题。感觉比较重要

1、采用了svg-sprite-loader会导致源文件加载,导致无法用css加载svg图片

扫描二维码关注公众号,回复: 13166686 查看本文章

2、不用呢兼容性下降。但是通用性高了很多。

看大家取舍吧

猜你喜欢

转载自juejin.im/post/7017657405265674271
SVG