Vue3 svg加载iconfont
web老猴子 人气:1安装依赖
由于我们是Vue3项目,可以使用vite
来快速创建一个Vu3项目:
npm install -g yarn yarn create vite my-vue-app --template vue // 这里我们使用vue模板,默认是Javascript语法,如果需要ts语法则需要指定模板为vue-ts cd my-vue-app yarn yarn dev
创建好项目后,我们再来引入Element Plus
,安装并引入的过程如下:
安装
:
yarn add element-plus
完整引入
:
// main.js ... import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' app.use(ElementPlus)
引入后,我们就可以在Vue3项目中使用了:
<template><el-button>按钮</el-button> </template>
Element Plus使用Icon会比Element UI稍微麻烦点。首先我们需要安装Icon的依赖:
yarn add @element-plus/icons-vue
我们在main.js
中注册所有的图标,当然也可以按需引入图标:
// main.js // 全局引入 import * as ElementPlusIconsVue from '@element-plus/icons-vue' ... for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, component) }
el-icon
的使用:
<template><el-icon><Edit /></el-icon> </template> <script setup> // import {Edit} from '@element-plus/icons-vue' // 按需引入,如果已经全局引入了就不需要按需引入 </script>
Element Plus的el-icon
使用的是svg
,这与Element UI使用的类名有很大的不同,也就是说我们无法直接在el-icon
中使用iconfont
的图标。虽然Element Plus的图标已经能满足大部分场景的需求,但是一些特殊场景只能从iconfont
或者自定义的图标上获取。
那么有没有办法将iconfont
封装成svg,并给el-icon
调用呢?
将iconfont封装成svg
可缩放矢量图形(Scalable Vector Graphics),简称SVG,是一种基于XML的,可用于描述二维的矢量图形。SVG可以优雅而简洁的渲染不同大小的图形,并且可以被无限缩放并且保持不失真或者降低质量,这一特性比JPEG
、PNG
等好用太多。SVG的内容相当多,感兴趣的可以去MDN上查看文档:SVG。我们这里只是简单实用SVG来封装iconfont。
首先我们新建一个SvgIcon.vue
的文件,
<template><svg :class="classList" aria-hidden="true"> <use :xlink:href="iconName" rel="external nofollow" :fill="color" /></svg> </template> <script setup> import { computed } from 'vue'; const props = defineProps({className: { type: String, default: ''},iconClass: { type: String, required: true},color: { type: String, default: '#409eff'},size: { type: String, default: '20px'} }) const classList = computed(() => {return ['icon', props.className || ''] }) const iconName = computed(() => {return `#${props.iconClass}` }) </script> <style scoped> .icon {/* v-bind是Vue3才支持的功能,可以将CSS的值与js的值绑定 */width: v-bind('props.size');height: v-bind('props.size');position: relative;vertical-align: -2px;fill: currentColor; } </style>
这样就将iconfont
封装成了svg来调用了,这里我们重点说几个属性:
- aria-hidden:默认为false,设置为true表示会把整个元素包括子元素从可访问树(AOM)上移除,但是在DOM树上还是存在的
- xlink:href:use元素的属性
- v-bind:Vue3的特性,可用于关联CSS和js
- fill:如果在动画接收还需要保持动画的值,可用于设置颜色
如何使用
使用已经封装好的SvgIcon.vue
比较简单,就和正常的组件一样使用即可。例如:
<template><SvgIcon :icon-class="icon-pointer"></SvgIcon> </template> <script setup> import SvgIcon from './SvgIcon.vue' </sript>
如果不想在局部注册组件,也可以注册为全局组件:
// main.js import SvgIcon from '@/SvgIcon.vue' ... app.component('SvgIcon', SvgIcon);
作为SVG组件,我们也可以直接使用在el-icon
中,这样就可以添加任意iconfont
到el-icon
中了:
<template><el-icon><SvgIcon :icon-class="icon-pointer"></SvgIcon></el-icon> </template>
按理说到这里,本篇教程就应该结束了。但是,在使用的过程中,按照正常的方式设置的hover
样式不生效,笔者尝试了几种方案,最终放弃hover
,采用监听鼠标事件的方式解决。
设置”hover“样式
SVG不同于class
样式,其无法直接通过修改hover
样式来设置鼠标悬浮在图标上面时颜色改变,这个时候我们就需要换一种思路了。我们在SvgIcon.vue
中传入了color
,并且通过fill
将color
作用到SVG上,因此我们可以在父组件中修改color
的值来实现"hover"效果。
<template><div @mouseenter="() => handleMouseenter" @mouseleave="() => handleMouseleave"><SvgIcon :icon-class="icon-pointer" :color="color"></SvgIcon></div> </template> <script setup> import {ref} from 'vue' const color = ref('red') const handleMouseenter = () => {color.value = 'blue' } const handleMouseleave = () => {color.value = 'red' } </sript>
上面的例子中适用于单个SvgIcon
,如果是多个的话,就需要进一步改造了:
<template><div v-for="(item, index) in list" @mouseenter="($event) => handleMouseenter($event, index)" @mouseleave="($event) => handleMouseleave($event, index)"><SvgIcon :icon-class="icon-pointer" :color="hoverIconIndex == index ? 'blue' : 'red'"></SvgIcon></div> </template> <script setup> import {ref} from 'vue' const list = ref([{name: '张三'} ]) const color = ref('red') const hoverIconIndex = ref(-1) const handleMouseenter = (event, index) => {hoverIconIndex.value = index; } const handleMouseleave = (event, index) => {hoverIconIndex.value = -1; } </sript>
对比来看,其实也不复杂。
为什么图标颜色无法修改?
可能有点朋友按照上述的步骤操作后,发现并不能修改图标颜色,如果不是代码有误,那应该就是导入的iconfont有问题。一般我们会直接在iconfont官网下载图标:
将下载好的压缩包解压后,只复制iconfont.js
到项目中即可:
// main.js ... import '@/assets/iconfont/iconfont.js';
我们来看一下iconfont.js
中icon-close1
和icon-close
的源码:
可以发现,这两个图标最大的差别就是一个有fill
,另一个没有,而这就是问题的关键。如果某一个图标的fill不为空,那么作为svg引用时将无法修改填充色。
举个例子:
<template><div> <SvgIcon :color="'red'" :icon-class="'icon-close'"></SvgIcon> <SvgIcon :color="'red'" :icon-class="'icon-close1'"></SvgIcon> </div> </template>
运行结果:
遇到这个问题应该怎么解决呢,一种方式就是手动删除所有Icon的fill
属性,另一个就是在iconfont上面使用批量去色。
批量去色后,我们再次下载图标,并解压后替换掉原来的iconfont.js
,再去源码看看就会发现所有图标的fill
都没有了,而且也可以修改颜色。
总结
本文详细介绍了如何在Element Plus中使用iconfont,简单的说就是要将其封装成SVG,并且支持动态修改颜色。虽然操作上不难,但是容易踩一些坑,你学会了吗?
加载全部内容