Nuxtjs 项目使用 svg-sprite-loader 更改 svg 的颜色
前言
由于一些原因,最新的公司项目要使用的技术切换到了 Nuxt.js
,也就是 Vue
的 ssr 服务端渲染框架。
项目需求
在新项目的开发过程中,遇到了一个需求:有一栏带 icon 的 tab,要实现鼠标悬浮和 tab 在激活状态下,icon 和文字一起改变颜色。
第一次开发
解决思路
在之前使用 svg
icon,都是直接把它放进 img
里来使用的,也就是这样:
<img src='assest/svg/icon_xxx.svg' />
这样的形式。这次开发我第一时间想到的还是这样的引入形式,然后在鼠标悬浮和激活时,把其替换成 active 状态的 icon,也就是这样:
<img v-if="active" src='assest/svg/icon_xxx_active.svg' />
<img class="icon-xxx" v-else src='assest/svg/icon_xxx.svg' />
//...
<style lang="scss" scoped>
.icon-xxx {
&:hover {
content: url(assets/svg/icon_xxx_active.svg);
}
}
</style>
问题
由于激活和未激活状态下,使用的并不是同一个 icon,在网速有点慢的情况下,就会出现,鼠标悬浮上去,icon 消失的情况。这是因为 active
的 icon 还没加载出来。那这样的体验无疑是很差的。
第二次开发
解决思路
不能用两个 icon 互相替换这样的形式。应该使用同一个 icon,并且在激活状态下更改它的颜色。那么通过 img
标签引入 svg
这样的形式肯定是不行的了。
然后找到了解决方案:svg-sprite-loader
第二次开发
- 安装依赖
yarn add --dev svg-sprite-loader
- 创建
SvgIcon
组件
在 components
目录下创建 SvgIcon.vue
文件
<template>
<svg :class="svgClass" aria-hidden="true">
<use :href="iconName"></use>
</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 lang="scss" scoped>
.svg-icon {
fill: currentColor !important;
overflow: hidden;
}
</style>
- 一次性引入全部 icon
在 plugins
目录下,创建文件 svg-icon.js
import Vue from 'vue'
import SvgIcon from '~/components/SvgIcon'
// 注册组件
Vue.component('SvgIcon', SvgIcon)
const req = require.context('~/assets/svg', true, /.svg$/)
const requireAll = (requireContext) => requireContext.keys().map(requireContext)
requireAll(req)
- 修改
build
配置 修改nuxt.config.js
文件
const { resolve } = require('path')
const nuxtConfig = {
//...
plugins: [
//...,
'~/plugins/svg-icon',
],
build: {
//...
extend(config, ctx) {
const svgRule = config.module.rules.find((rule) =>
rule.test.test('.svg')
)
svgRule.exclude = [resolve(__dirname, 'assets/svg')]
config.module.rules.push({
test: /.svg$/,
include: [resolve(__dirname, 'assets/svg')],
use: [
{
loader: 'svg-sprite-loader',
options: { symbolId: 'icon-[name]' },
},
],
})
},
}
}
- 使用
这时,我们可以在代码里使用 svg-icon
组件,但是还有一个要注意的问题:在 svg 文件中,要将其颜色的 fill
属性的值修改为 currentColor
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ThumbsUp</title>
<g id="xxx" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="xxx" transform="translate(-80.000000, -202.000000)">
<g id="xxx" transform="translate(66.000000, 168.000000)">
<g id="ThumbsUp" transform="translate(14.000000, 34.000000)">
<rect id="矩形" x="0" y="0" width="20" height="20"></rect>
<path d="M18.1141664,6.25907891 C17.7581668,5.8560092 17.2463006,5.62510827 16.7085266,5.625 L12.4995422,5.625 L12.4995422,4.375 C12.4975824,2.64992258 11.0996196,1.25195979 9.37454219,1.25 C9.1378058,1.25 8.92138498,1.38374168 8.81553672,1.59549688 L5.86326563,7.5 L2.49954219,7.5 C1.80951339,7.50078916 1.25033135,8.05997121 1.24954219,8.75 L1.24954219,15.625 C1.25033135,16.3150288 1.80951339,16.8742108 2.49954219,16.875 L15.7710266,16.875 C16.7161444,16.8736603 17.5130326,16.1701949 17.631607,15.2325437 L18.569107,7.73254375 C18.6356533,7.19888546 18.4699883,6.66232865 18.1141664,6.25907891 Z M2.49954219,8.75 L5.62454219,8.75 L5.62454219,15.625 L2.49954219,15.625 L2.49954219,8.75 Z" id="形状" fill="currentColor" fill-rule="nonzero"></path>
</g>
</g>
</g>
</g>
</svg>
然后,在我们的代码里使用 svg-icon
组件啦!
<template>
<svg-icon icon-class="icon_xxx" /> // icon-class 对应的是 icon 的名字
</template>
<style lang="scss" scoped>
svg {
color: red;
&:hover {
color: black;
}
}
</style>
此时,svg
修改颜色就完成了
总结
使用 svg-sprite-loader
会让你的 svg
引入写起来非常的舒服,可以随意修改其颜色,就是配置起来稍稍麻烦一点。但对比开发体验来说,这点时间花费,是完全值得的!
转载自:https://juejin.cn/post/7148730973247504415