一、vue2+webpack
1.npm安装依赖包
npm i svg-sprite-loader
package.json
"svg-sprite-loader": "^5.0.0"
main.js
import { registerSvgIconComp } from '@/plugins/registerSvgIcon'
registerSvgIconComp(app)
vue.config.js文件
module.exports = {
publicPath: '/',
// 打包输出
outputDir: 'dist',
// 链式webpack配置
chainWebpack: config => {
// 设置 svg-sprite-loader
config.module
.rule('svg')
.exclude.add(resolve('src/icons'))
.end()
config.module
.rule('icons')
.test(/\.svg$/)
.include.add(resolve('src/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
.end()
},
}
2.组件封装
/plugins/registerSvgIcon.js
// svg-icon
import SvgIcon from '@/components/SvgIcon'
const req = require.context('@/icons/svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)
export function registerSvgIconComp(app) {
app.component('SvgIcon', SvgIcon)
}
/components/SvgIcon
<template>
<view v-if="isExternalIcon" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-bind="$attrs"></view>
<svg v-else :class="svgClass" aria-hidden="true" v-bind="$attrs">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
import { isExternal } from '@/utils/validate'
import { computed } from 'vue'
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true,
},
className: {
type: String,
default: '',
},
},
setup(props) {
console.log('props.iconClass :>> ', props.iconClass)
console.log('props.className', props.className)
const isExternalIcon = computed(() => isExternal(props.iconClass))
const iconName = computed(() => `#icon-${props.iconClass}`)
const svgClass = computed(() => {
if (props.className) {
return 'svg-icon ' + props.className
} else {
return 'svg-icon'
}
})
const styleExternalIcon = computed(() => {
return {
mask: `url(${props.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${props.iconClass}) no-repeat 50% 50%`,
}
})
return {
isExternalIcon,
iconName,
svgClass,
styleExternalIcon,
}
},
}
</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>
3.组件调用
<div>
<svg-icon icon-class="ic-tips" /> 验证码
</div>
二、vue3+vite
1.npm安装依赖包(这是npm截止笔记时间最新包,我用的不是最新的)
npm i vite-plugin-svg-icons@0.6.0-beta.1
package.json
"vite-plugin-svg-icons": "^2.0.1"
2.main.js配置
// svg-icon
import 'vite-plugin-svg-icons/register'// 看哪个管用
// import 'virtual:svg-icons-register' // 看哪个管用
//组件全局调用
import { registerSvgIconComp } from '@/plugins/registerSvgIcon'
registerSvgIconComp(app)
3.组件封装
/plugins/registerSvgIcon.js
// svg-icon
import SvgIcon from '@/components/SvgIcon'
const files = import.meta.globEager('../static/icons/svg/*.svg') // vite
const modules = {}
const requireAll = (files) => {
for (const key in files) {
if (Object.prototype.hasOwnProperty.call(files, key)) {
modules[key.replace(/(\.\/|\.svg)/g, '')] = files[key].default
}
}
}
requireAll(files)
export function registerSvgIconComp(app) {
app.component('SvgIcon', SvgIcon)
}
/components/SvgIcon.vue
<template>
<view v-if="isExternalIcon" :style="styleExternalIcon" class="svg-external-icon svg-icon"></view>
<svg v-else :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
import { isExternal } from '@/utils/validate'
import { computed } from 'vue'
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true,
},
className: {
type: String,
default: '',
},
},
setup(props) {
const isExternalIcon = computed(() => isExternal(props.iconClass))
const iconName = computed(() => `#icon-${props.iconClass}`)
const svgClass = computed(() => {
if (props.className) {
return 'svg-icon ' + props.className
} else {
return 'svg-icon'
}
})
const styleExternalIcon = computed(() => {
return {
mask: `url(${props.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${props.iconClass}) no-repeat 50% 50%`,
}
})
return {
isExternalIcon,
iconName,
svgClass,
styleExternalIcon,
}
},
}
</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>
4.组件调用
<div>
<svg-icon icon-class="ic-tips" /> 验证码
</div>
注意:
uniapp转微信小程序失败:Error: 暂不支持 v-bind=“” 用法
原因就是字面意思,只能老老实实使用props接受父组件传参,一个个再传进去。包括父组件得行内样式style,反正就是不能偷懒。