一、icon组件
在项目中,会用到两种图标:element-plus自带图标和自定义图标
编写自定义组件展示自定义svg图标,这是一种通用方案
二、创建svgIcon组件
1.组件接受两个prop:icon和className
按需引入defineProps来定义接受的prop
import { defineProps, computed } from 'vue'// vue3 中defineProps用来接收propsconst props = defineProps({// icon路径icon: {type: String,required: true},// 图标类名className: {type: String,default: ''}})
2.需要三个计算属性:
(1)是否是外部图标
根据icon是否为http(s),tel,mailto开头来判断是否为外部图标,可以封装一个工具函数
export function isExternal(path) {/*** param path 资源路径*/return /^(https?:|mailto:|tel:)/.test(path)}
(2)外部图标样式
<template><div><!-- 展示外部图标 --><divv-if="isExternal":class="className":style="externalIconStyles"class="svg-external-icon svg-icon"></div><svg v-else :class="className" class="svg-icon" aria-hidden="true"><use :xlink:href="iconName"></use></svg><!-- 展示内部图标 --></div></template>
(3)内部图标名
import { defineProps, computed } from 'vue'import { isExternal as isExternalValidation } from '@/utils/validate'// vue3 中defineProps用来接收propsconst props = defineProps({// icon路径icon: {type: String,required: true},// 图标类名className: {type: String,default: ''}})// 需要一些计算属性/*** 内部图标*//*** 外部图标样式*//*** 判断是否为外部图标*/// 判断一个资源是否为内部资源是一个常用方法,可以封装为一个工具const isExternal = computed(() => isExternalValidation(props.icon))// 外部图标样式const externalIconStyles = computed(() => ({mask: `url(${props.icon}) no-repeat 50% 50%`,'webkit-mask': `url(${props.icon}) no-repeat 50% 50%`}))// 内部图标添加一个统一前缀const iconName = computed(() => `#icon-${props.icon}`)
三、图标显示
1.外部图标显示
外部图标用div标签,给div绑定mask属性便可显示svg
{mask: `url(${props.icon}) no-repeat 50% 50%`,'webkit-mask': `url(${props.icon}) no-repeat 50% 50%`}
2.内部图标
require.context
多个内部图标需要先注册,使用webpack的require.context方法可以创建一个上下文(返回一个require函数),可以自动导入某个文件下多个子文件,不用重复调用import
require.context(directory,(useSubdirectories = true),(regExp = /^\.\/.*$/),(mode = 'sync'));
require函数
返回的require函数有三个属性,还可以接收一个request参数这里主要用到了函数的keys方法(返回相对文件名路径)
(1)将路径作为request参数传入require函数进行svg导入
(2)引入svg-icon进行全局注册
// 导入所有svg图标// 将SvgIcon组件进行全局注册import SvgIcon from '@/components/svgIcon/index.vue'const svgRequire = require.context('./svg', false, /\.svg$/)// svgRequire 是一个函数,接受一个request参数,该函数有三个属性/*** resolve 函数,返回request被解析后得到的模块id* keys 函数,返回文件数组,这里返回svg图标* id 返回context module的id*/// 将svgRequire.keys返回的的文件名作为request参数传入svgRequire,进行图标注册svgRequire.keys().forEach((svgIcon) => svgRequire(svgIcon))export default (app) => {app.component('svg-icon', SvgIcon)
3.svg-sprite-loader
使用内部图标后,无法显示,是因为项目中不能处理svg的loader
(1)安装loader
cnpm i svg-sprite-loader@6.0.9 --save--dev
(2)添加配置
const path = require('path')function resolve(dir) {return path.join(__dirname, dir)}module.exports = {chainWebpack(config) {// 设置 svg-sprite-loaderconfig.module.rule('svg').exclude.add(resolve('src/icon')).end()config.module.rule('icons').test(/\.svg$/).include.add(resolve('src/icon')).end().use('svg-sprite-loader').loader('svg-sprite-loader').options({symbolId: 'icon-[name]'}).end()}}
