Rodrick

vuePress-theme-reco Rodrick    2022
Rodrick Rodrick

Choose mode

  • dark
  • auto
  • light
Home
Category
  • CS基础
  • 数据库
  • 前端
  • 其他
Tag
About
Timeline
D&T
  • 官方文档

    • Vue
    • Vue3
    • Webpack
    • MDN
    • Node中文网
    • React
    • 小程序
    • FineReport
  • 学习面试

    • 现代JavaScript教程
    • ES6
    • 阿西河
    • LeetCode
    • 牛客网
  • 工具

    • bejson
Contact
  • Github
  • Gitee
author-avatar

Rodrick

62

Article

18

Tag

Home
Category
  • CS基础
  • 数据库
  • 前端
  • 其他
Tag
About
Timeline
D&T
  • 官方文档

    • Vue
    • Vue3
    • Webpack
    • MDN
    • Node中文网
    • React
    • 小程序
    • FineReport
  • 学习面试

    • 现代JavaScript教程
    • ES6
    • 阿西河
    • LeetCode
    • 牛客网
  • 工具

    • bejson
Contact
  • Github
  • Gitee
  • vue全家桶

    • vue基础
    • vue-cli使用说明
    • vue-router
    • vuex
    • 浅谈组件通讯
    • mapGetters & mapActions
    • mixin(混入)基本使用
    • vuecli 配合 svg-sprite-loader 使用svg
    • 实现一个mini版的Vue
    • 初探vue3

vuecli 配合 svg-sprite-loader 使用svg

vuePress-theme-reco Rodrick    2022

vuecli 配合 svg-sprite-loader 使用svg

Rodrick 2020-11-16 vueWebpack

# 前言

svg-sprite-loader  的插件,用来根据导入的 svg 文件自动生成 symbol 标签并插入 html,接下来就可以在模版中方便地使用 svg-sprite 技术了。

# 安装插件

npm install svg-sprite-loader -D

# webpack 配置

在 vue.config.js 中加入如下配置:

const path = require('path')

function resolve(dir) {
  return path.join(__dirname, './', dir)
}

module.exports = {
  chainWebpack: config => {
    // svg rule loader
    const svgRule = config.module.rule('svg') // 找到svg-loader
    svgRule.uses.clear() // 清除已有的loader, 如果不这样做会添加在此loader之后
    // svgRule.exclude.add(/node_modules/) // 正则匹配排除node_modules目录
    svgRule.include.add(resolve('src/assets/img/icons')) 
    svgRule // 添加svg新的loader处理
      .test(/\.svg$/)
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })

    // 修改images loader 添加svg处理
    const imagesRule = config.module.rule('images')
    imagesRule.exclude.add(resolve('src/assets/img/icons'))
    config.module
      .rule('images')
      .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)

    // config.module.rules.delete("svg"); //重点:删除默认配置中处理svg,
    // config.module
    //   .rule('svg-sprite-loader')
    //   .test(/\.svg$/)
    //   .include
    //   .add(resolve('src/assets/img/icons')) //处理svg目录
    //   .end()
    //   .use('svg-sprite-loader')
    //   .loader('svg-sprite-loader')
    //   .options({
    //     symbolId: 'icon-[name]'
    //   })
  }
}

关于 webpack 的配置是重点,这里上下两种只是两种不同的写法,本质一样

参考:官网说明
这里配置主要做了这些事:

  • 清除 默认 Loader
  • 将我们指定的存放 svg 的 icon 文件夹 include 进,并进行配置
  • 给默认的 image loader 添加 svg 处理,默认的配置是没有 svg 的,相关源码:
    // static assets -----------------------------------------------------------

    webpackConfig.module
      .rule('images')
        .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
        .use('url-loader')
          .loader(require.resolve('url-loader'))
          .options(genUrlLoaderOptions('img'))

    // do not base64-inline SVGs.
    // https://github.com/facebookincubator/create-react-app/pull/1180
    webpackConfig.module
      .rule('svg')
        .test(/\.(svg)(\?.*)?$/)
        .use('file-loader')
          .loader(require.resolve('file-loader'))
          .options({
            name: genAssetSubPath('img'),
            esModule: supportsEsModuleAsset
          })
  • images loader 中排除我们指定的 svg icon 文件夹

# 创建 SvgIcon 组件

SvgIcon.vue

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

<script>
export default {
  name: "SvgIcon",
  props: {
    iconClass: {
      type: String,
      required: true,
    },
    className: {
      type: String,
      default: "",
    },
  },
  computed: {
    iconName() {
      return `#icon-${this.iconClass}`;
    },
    svgClass() {
      if (this.className) {
        return "svg-icon " + this.className;
      } else {
        return "svg-icon";
      }
    },
  },
};
</script>

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

简单来说这个组件的作用是:

  • 给 svg 添加指定的 className
  • 根据传入的 iconClass 生成 iconName 去寻找对应的 svg icon

# 创建 icons 存放目录


icon 存放路径根据情况选择,这个路径就是我们刚才 webpack 配置的路径,icons 文件夹内结构保持如图不变:
image.png
svg 文件夹用来存放 svg icon,index.js 内容如下:

import Vue from 'vue'
import SvgIcon from '@/components/common/svgicon/SvgIcon' // svg组件

// 注册到全局
Vue.component('svg-icon', SvgIcon)

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

注意点:

  • SvgIcon 组件路径保持正确
  • 这里是注册到了全局中,如果有需要单独引入也可以

# 在 main.js 中引入

import 'assets/img/icons/index'

# 使用

在需要使用的时候,加入需要引入 svg 文件夹下的 head.svg 直接使用如下:
className 传入 class 名, iconClass 传入 svg 文件名

<template>
  <div id="user-info">
    <svg-icon iconClass="head" className="privateImage-svg"></svg-icon>
  </div>
</template>

<script>
	export default {
		name: "UserInfo"
	}
</script>

<style scoped>
  #user-info .privateImage-svg {
    width: 60px;
    height: 60px;
    background-color: #fff;
    border-radius: 30px;
  }
</style>
欢迎来到 Rodrick
看板娘