1. Install dependencies
First of all, you need to install the svg-sprite-loader dependency. The command is as follows. During the learning process, the icon was unable to display normally because the dependency was not downloaded.
npm install svg-sprite-loader --save-dev --force
2. Configure svg image processing rules
By using the svg-sprite-loader component, the svg icon file is produced into a Sprite image (Sprite), which is configured in the vue.config.js file, as follows:
//用于导入Node.js核心模块 path 的方法。path 模块提供了处理文件路径的实用工具,可以用于处理和操作文件路径字符串。
const path = require('path')
//定义了一个名为 resolve 的函数,用于将相对路径转换为绝对路径。__dirname 是 Node.js 中的一个全局变量,表示当前模块文件所在的目录的绝对路径。
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
lintOnSave: false,
transpileDependencies: ["vue"],
publicPath: '/sys', // 设置上下文路径,与Tomcat或Nginx中的上下文路径保持一致
indexPath: 'index.html', // 相对于打包路径index.html的路径
outputDir: 'sys', // 'dist', 生产环境构建文件的目录
productionSourceMap: true,
devServer: {
port: 8881,
headers: {
'Access-Control-Allow-Origin': '*',
}
},
chainWebpack(config) {
//覆盖默认配置中处理svg的规则
config.module
.rule('svg')//定义规则名称,必须为svg,为了覆盖该规则
.exclude.add(resolve('src/components/SvgIcon'))
.end()
//定义处理指定目录下svg图片的规则
config.module
.rule('icons1')//定义规则名称,可以自定义
.test(/\.svg$/)//表示该规则只适用于后缀为 .svg 的文件。
.include.add(resolve('src/components/SvgIcon'))//只对这个目录下的SVG文件应用该规则。
.end()
.use('svg-sprite-loader')// 指定了使用 svg-sprite-loader 这个loader来处理满足该规则的SVG文件。
.loader('svg-sprite-loader')//指定了要使用的loader为 svg-sprite-loader。
.options({
//对 svg-sprite-loader 的配置选项,通过 symbolId 可以设置每个图标的标识符,这里使用 icon-[name] 表示使用图标文件的名称作为标识符。
symbolId: 'icon-[name]'
})
.end()
}
};
Sprite is a technology that combines multiple small icons or pictures into one large image. By placing multiple icons on the same picture and controlling the display of different icon positions through the CSS background-position property, you can reduce the number of network requests and improve page loading speed and performance.
3. Define the svg-icon component
The svg-icon component includes three parts: svg file (svg image), index.vue and index.js. Among them, the svg file mainly includes the svg file corresponding to each icon. The configuration in the vue.config.js file mentioned above is to generate a sprite image from the file under the file; index.vue is used to define the vue component of the icon; index. js implements the registration of svg-icon component. The specific implementation is as follows:
index.vue page, the code is as follows:
<template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
import {
isExternal } from '@/utils/validate'
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
isExternal() {
return isExternal(this.iconClass)
},
iconName() {
return `#icon-${
this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
},
styleExternalIcon() {
return {
mask: `url(${
this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${
this.iconClass}) no-repeat 50% 50%`
}
}
}
}
</script>
<style scoped>
.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;
}
</style>
index.js file, the code is as follows:
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon/index.vue'// svg component
// 注册
Vue.component('svg-icon', SvgIcon)
//在当前文件所在目录下的 ./svg 目录中查找所有以 .svg 结尾的文件,并将匹配的文件创建一个模块上下文
const req = require.context('./svg', false, /\.svg$/)
//将模块上下文中的所有模块导入,并注册为SvgIcon组件的子组件。
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)
Processed data:
4. Use and display of svg icons
A page that displays all svg icons is implemented here, including the svg-icons.js file and the index.vue file. Among them, svg-icons.js mainly reads the names of all svg icons; index.vue defines the display icon page.
The svg-icons.js code is implemented as follows, similar to the above index.js file, reading the file directory and obtaining the file name:
const req = require.context('../SvgIcon/svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys()
const re = /\.\/(.*)\.svg/
const svgIcons = requireAll(req).map(i => {
return i.match(re)[1]
})
console.log(svgIcons);
export default svgIcons
The code for index.vue page is implemented as follows:
<template>
<div class="icons-container">
<el-tabs type="border-card">
<el-tab-pane label="Icons">
<div v-for="item of svgIcons" :key="item">
<el-tooltip placement="top">
<div slot="content">
{
{ generateIconCode(item) }}
</div>
<div class="icon-item">
<svg-icon :icon-class="item" class-name="disabled" />
<span>{
{ item }}</span>
</div>
</el-tooltip>
</div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import svgIcons from './svg-icons'
export default {
name: 'Icons',
data() {
return {
svgIcons
}
},
methods: {
generateIconCode(symbol) {
return `<svg-icon icon-class="${
symbol}" />`
}
}
}
</script>
<style lang="scss" scoped>
.icons-container {
margin: 10px 20px 0;
overflow: hidden;
.icon-item {
margin: 20px;
height: 85px;
text-align: center;
width: 100px;
float: left;
font-size: 30px;
color: #24292e;
cursor: pointer;
}
span {
display: block;
font-size: 16px;
margin-top: 10px;
}
.disabled {
pointer-events: none;
}
}
</style>