Vue3 对feather-icons封装 并且扩展图标

491 阅读1分钟

最近项目需要开发权限管理相关的内容 在开发菜单管理相关功能时 遇到了一个小问题 就是在进行菜单编辑时需要自定义菜单图标 当时使用的是feather-icons这个库,菜单中有一个特殊的模块找不到合适的图标(就是这个图标)

taji.png 就用的png图片代替,但是现在在要对菜单进行编辑就不能这样写了 然后就想着对feather-icons进行扩展

首先 要把这个图片转 svg 转好后是下面这个样子
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
x="0px" y="0px" width="151px" height="151px" viewBox="0 0 151 151" enable-background="new 0 0 151 151" 
xml:space="preserve">  <image id="image0" width="151" height="151" x="0" y="0"
    href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJcAAACXAgMAAABl8SHqAAAABGdBTUEAALGPC/xhBQAAACBjSFJN
AAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAADFBMVEX///+ttNKttNL///9P
oVYjAAAAAnRSTlMAAHaTzTgAAAABYktHRACIBR1IAAAACXBIWXMAABcSAAAXEgFnn9JSAAAAB3RJ
TUUH5ggZCAQgQLm1nwAAAbRJREFUWMPt2DtyxCAMBuA9YhoodASdJo2bVGko0CmDeJm1WfhnQiae
xGq2+dZaJBnjfTzu+MkwJUhCbKYbbztjZQ5jfsrkV5jT1S5ilJibMNbShhKPmZXM/JBxZPZFvyqT
ymTAqGHuNeOGddJmVpJZ2bqtyCzk/MjM9tJmFq6QGhAScidtYuEKLjMXF+27LFzA7IzOaRPTr+8s
pu0w0h/DvjJ7ShuZ5mxZKfYzs/GnJMautE6OLOYszNdyuycW77theGVTpelXsm0pc8rOQ3gIlHmI
McgEYoSyDWEWZQ5hoSIrGQvECGXvCLPKkPi8NCOE1Q0/P63ah1bcYVO5bvZ9Fu6gm/1PBk7IFRiV
h+mYcWJ+wmQpe5X00AWQUTovuwmz8YB1Lsix9ZqPZToheurJx70RY23WnIU1lPeH8Vg6hqbX5xUM
WXPCHDKu59oho3oOHTJbT7+jIVdmAGZAxv7CDCpIYEh50/sGxLZ1zCDTG9sFsvkt0xR4EaMps2mr
gdg8KcxclzUftbQCsJRgxsK0CcREgGcWYcz2d6Qj043LAYywrcbYrCasRvmX4Dn+JrvjAvEFdCof
rdRIlUcAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjItMDgtMjVUMDg6MDQ6MzIrMDA6MDDP8Jr7AAAA
JXRFWHRkYXRlOm1vZGlmeQAyMDIyLTA4LTI1VDA4OjA0OjMyKzAwOjAwvq0iRwAAAABJRU5ErkJg
gg==" />
</svg>
接下来就是在封装组件时把这个特殊的图标加进去
<template>
  <i :class="classes" v-html="activity" style="line-height: 0"></i>
</template>

<script>
import { icons } from 'feather-icons';
import VueTypes from 'vue-types';
import { toRefs, watchEffect, ref } from 'vue';

export default {
  name: 'FeatherIcons',
  props: {
    type: VueTypes.string.def('activity'),
    size: VueTypes.oneOfType([VueTypes.number, VueTypes.string]).def(16),
    stroke: VueTypes.oneOfType([VueTypes.number, VueTypes.string]).def(2),
    classes: VueTypes.string,
    color: VueTypes.string,
    fill: VueTypes.string.def('transparent'),
  },
  setup(props) {
    const { size, color, fill, type, stroke, classes } = toRefs(props);
    // console.log(icons);
    icons['tower-crane'] = {
      name: 'tower-crane',
      contents:
        '<image id="image0" width="24" height="24" x="0" y="0" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJcAAACXAgMAAABl8SHqAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAADFBMVEX///+ttNKttNL///9PoVYjAAAAAnRSTlMAAHaTzTgAAAABYktHRACIBR1IAAAACXBIWXMAABcSAAAXEgFnn9JSAAAAB3RJTUUH5ggZCAQgQLm1nwAAAbRJREFUWMPt2DtyxCAMBuA9YhoodASdJo2bVGko0CmDeJm1WfhnQiaexGq2+dZaJBnjfTzu+MkwJUhCbKYbbztjZQ5jfsrkV5jT1S5ilJibMNbShhKPmZXM/JBxZPZFvyqTymTAqGHuNeOGddJmVpJZ2bqtyCzk/MjM9tJmFq6QGhAScidtYuEKLjMXF+27LFzA7IzOaRPTr+8spu0w0h/DvjJ7ShuZ5mxZKfYzs/GnJMautE6OLOYszNdyuycW77theGVTpelXsm0pc8rOQ3gIlHmIMcgEYoSyDWEWZQ5hoSIrGQvECGXvCLPKkPi8NCOE1Q0/P63ah1bcYVO5bvZ9Fu6gm/1PBk7IFRiVh+mYcWJ+wmQpe5X00AWQUTovuwmz8YB1Lsix9ZqPZToheurJx70RY23WnIU1lPeH8Vg6hqbX5xUMWXPCHDKu59oho3oOHTJbT7+jIVdmAGZAxv7CDCpIYEh50/sGxLZ1zCDTG9sFsvkt0xR4EaMps2mrgdg8KcxclzUftbQCsJRgxsK0CcREgGcWYcz2d6Qj043LAYywrcbYrCasRvmX4Dn+JrvjAvEFdCofrdRIlUcAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjItMDgtMjVUMDg6MDQ6MzIrMDA6MDDP8Jr7AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIyLTA4LTI1VDA4OjA0OjMyKzAwOjAwvq0iRwAAAABJRU5ErkJggg==" />',
      tags: ['warning', 'alert', 'danger'],
      attrs: {
        xmlns: 'http://www.w3.org/2000/svg',
        width: 24,
        height: 24,
        viewBox: '0 0 24 24',
        fill: 'none',
        version: '1.1',
        id: 'Layer_1',
        stroke: 'currentColor',
        color: '#000',
        'stroke-width': 2,
        'stroke-linecap': 'round',
        'stroke-linejoin': 'round',
        class: 'towercrane',
      },
    };
    //  icons['tower-crane']上面没有toSvg这个方法 所以要继承一下
    icons['tower-crane'].__proto__ = icons.activity.__proto__;
    let activity = ref(
      icons[type.value].toSvg({
        'stroke-width': stroke.value,
        width: size.value,
        height: size.value,
        color: color.value,
        fill: fill.value,
        class: classes.value,
      }),
    );
    watchEffect(() => {
      activity.value = icons[type.value].toSvg({
        'stroke-width': stroke.value,
        width: size.value,
        height: size.value,
        color: color.value,
        fill: fill.value,
      });
    });

    return {
      activity,
    };
  },
};
</script>

<style lang="scss" scoped></style>