svgsprite的svg-sprite-loader在vue中的使用及vue-cli如何配置

根据本人在项目的实践提炼出来,在说svg-sprite-loader使用之前,我们先看一下具体效果:
在这里插入图片描述

目录结构
  1. 把svg图放置在assets/icons/svg下,
    在这里插入图片描述
  2. /assets/icons/index.js 注入全局组件
import Vue from 'vue'

import SvgIcon from '@/components/SvgIcon'

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

  1. 在main.js引入 icons
import './assets/icons'
  1. 在components文件夹下新建两个组件
    在这里插入图片描述

SvgIcon 是元组件,即需要全局注册的组件svg-icon,代码如下

// components/SvgIcon/index.vue
<template>
  <svg
    :class="`${svgClass} ${spin ? 'scoped-svg-animation' : ''}`"
    aria-hidden="true"
    v-on="$listeners"
  >
    <use :xlink:href="iconName" />
  </svg>
</template>
<script>
export default {
  name: 'SvgIcon',
  props: {
    name: {
      type: String,
      required: true,
    },
    className: {
      type: String,
      default: '',
    },
    // 是否旋转
    spin: {
      type: Boolean,
      default: false,
    },
  },
  computed: {
    iconName() {
      return `#icon-${this.name}`
    },
    svgClass() {
      if (this.className) {
        return 'scoped-svg-icon ' + this.className
      } else {
        return 'scoped-svg-icon'
      }
    },
  },
}
</script>
<style lang="less">
.scoped-svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
  &.scoped-svg-animation {
    animation: rotate 2s linear infinite;
  }
  @keyframes rotate {
    from {
      transform: rotate(0deg);
    }
    to {
      transform: rotate(360deg);
    }
  }
  &.gray {
    color: #666;
  }
  &.white {
    color: #fff;
  }
}
</style>

项目中使用svg-icon组件:

//  /components/IconSelect/index.vue
<template>
  <div class="icon-select-wrapper">
    <div>当前选择:{{ currentIcon }}</div>
    <el-input v-model="iconVal" placeholder="请输入内容"></el-input>
    <div>
      <ul class="icon-list">
        <li
          :class="{ active: item === currentIcon }"
          v-for="(item, index) in iconList"
          :key="index"
          @click="selectIcon(item)"
        >
          <svg-icon
            :class-name="item === currentIcon ? 'white' : 'gray'"
            :name="item"
            style="width: 30px; height: 30px"
          />
          <span class="icon-label">{{ item }}</span>
        </li>
      </ul>
    </div>
  </div>
</template>
<script>
import icons from './config'
export default {
  data() {
    return {
      iconList: icons,
      iconVal: '',
      currentIcon: 'add-circle',
      iconClass: '',
    }
  },
  watch: {
    iconVal(val) {
      if (val) {
        this.iconList = this.iconList.filter((item) => item.indexOf(val) > -1)
      } else {
        this.iconList = icons
      }
    },
  },
  methods: {
    selectIcon(item) {
      this.currentIcon = item
      this.iconClass
    },
  },
}
</script>

<style lang="less">
.icon-select-wrapper {
  width: 450px;
}
.icon-list {
  width: 450px;
  display: flex;
  flex-wrap: wrap;
  border-left: 1px solid #dcdfe6;
  border-top: 1px solid #dcdfe6;
  margin-top: 20px;
  li {
    width: 150px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    border-right: 1px solid #dcdfe6;
    border-bottom: 1px solid #dcdfe6;
    padding: 10px 0;
    box-sizing: border-box;
    cursor: pointer;
    .icon-label {
      font-size: 12px;
      color: #666;
    }
    &.active {
      background: burlywood;
      .icon-label {
        font-size: 12px;
        color: #fff;
      }
    }
  }
}
</style>

使用require.context()方法自动化引入所有icons下的svg,并进行处理,取出svg的名称;
如 add.svg --> add

//  /components/IconSelect/config.js
const req = require.context('@/assets/icons/svg', false, /\.svg$/)
console.log(req, 'req')
const requireAll = (requireContext) => requireContext.keys()
const re = /\.\/(.*)\.svg/
const icons = requireAll(req).map((item) => {
  console.log(item, '88')
  return item.match(re)[1]
})
console.log(icons, 'icons')
export default icons

vue.config.js 配置svg-sprite-loader、svgo-loader如下:

const path = require('path')
function resolve(dir) {
  return path.join(__dirname, dir)
}
module.exports = {
  chainWebpack: (config) => {
  	// 不对assets/icons的svg打包
    config.module.rule('svg').exclude.add(resolve('src/assets/icons')).end()
    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add(resolve('src/assets/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]',
      })
      .end()
      .before('svg-sprite-loader')
      .use('svgo-loader')
      .loader('svgo-loader')
      .end()
  },
}

总结,在这个应用中,有如下知识点需要掌握了解:

1. require.context

它是webpack中的api,通过执行require.context函数获取一个特定的上下文,主要用来实现自动化导入模块,在前端工程中,如果遇到从一个文件夹引入很多模块的情况,可以使用这个api,它会遍历文件夹中的指定文件,然后自动导入,而不需要每次调用import导入模块

 require.context(directory, useSubdirectories = false, regExp = /^.//);

directory: 要查找的文件路径
useSubdirectories: 是否查找子目录
regExp: 要匹配文件的正则

在本例中,require.context()返回的结果如下:

var map = {
	"./add-circle.svg": "./src/assets/icons/svg/add-circle.svg",
	"./add.svg": "./src/assets/icons/svg/add.svg",
	"./arrow-double-right.svg": "./src/assets/icons/svg/arrow-double-right.svg",
	"./arrow-down.svg": "./src/assets/icons/svg/arrow-down.svg",
	"./arrow-right.svg": "./src/assets/icons/svg/arrow-right.svg",
	"./ashbin.svg": "./src/assets/icons/svg/ashbin.svg",
	"./bottom.svg": "./src/assets/icons/svg/bottom.svg",
	"./browse.svg": "./src/assets/icons/svg/browse.svg",
	"./column-3.svg": "./src/assets/icons/svg/column-3.svg",
	"./column-4.svg": "./src/assets/icons/svg/column-4.svg",
	"./direction-down.svg": "./src/assets/icons/svg/direction-down.svg",
	"./explain.svg": "./src/assets/icons/svg/explain.svg",
	"./file-open.svg": "./src/assets/icons/svg/file-open.svg",
	"./film.svg": "./src/assets/icons/svg/film.svg",
	"./folder-close.svg": "./src/assets/icons/svg/folder-close.svg"
};


function webpackContext(req) {
	var id = webpackContextResolve(req);
	return __webpack_require__(id);
}
function webpackContextResolve(req) {
	if(!__webpack_require__.o(map, req)) {
		var e = new Error("Cannot find module '" + req + "'");
		e.code = 'MODULE_NOT_FOUND';
		throw e;
	}
	return map[req];
}
webpackContext.keys = function webpackContextKeys() {
	return Object.keys(map);
};
webpackContext.resolve = webpackContextResolve;
module.exports = webpackContext;
webpackContext.id = "./src/assets/icons/svg sync \\.svg$";
2. svg标签use的使用

本例中:

<svg
    :class="`${svgClass} ${spin ? 'scoped-svg-animation' : ''}`"
    aria-hidden="true"
    v-on="$listeners"
  >
    <use :xlink:href="iconName" />
</svg>

渲染结果如下:
在这里插入图片描述

3. svg-sprite-loader
4. svgo-loader
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值