vue3+ts中使用自动导入图标插件后想动态渲染图标

1.问题描述

问题场景:做侧边栏的折叠效果时候需要根据settingStore.collapsed的值动态渲染图标,想用的是element-plus中的这两个图标。此处我的elementplus使用是按需引入。icon图标也是自动导入。
其他适用场景:根据路由的meta值,动态渲染icon图标,生成动态菜单。
在这里插入图片描述
解决方法: 使用h函数(见3解决方案)

2.探索过程

在vue3+ts中,用了自动导入图标插件unplugin-icons后,想动态渲染图标。
vite.config.ts中的相关配置:

 Icons({
        compiler: "vue3",
        autoInstall: true,
        //---start
        customCollections: {
          //custom图标集
          custom: FileSystemIconLoader(
            path.resolve(process.cwd(), "./src/assets/icons"),
            svg => svg.replace(/^<svg /, "<svg fill=\"currentColor\" ")
          )
        }
      }),

如果使用自己在assets里面放的svg图标是这样使用的(i+图标集名+图标名):

<ICustomHome/>

如果想使用element-plus里面的图标,前缀要这样写(i+图标集名ep+elementplus中的图标名)

      <IEpFold />

官网中竟然没有给出示例,我最开始还以为不能自动导入element-plus中的图标,还在手动引入,手动引入是这样写的:

import {
 Fold
} from "@element-plus/icons-vue";

<Fold/>

然后浏览器会解析成对应的svg
在这里插入图片描述
最初我用

  <component
        :is="settingStore.collapsed ? 'IEpFold' : 'IEpExpand'"
      ></component>

浏览器渲染出来的只是冰冷的

<IEpFold/>

而我们希望浏览器能将<IEpFold/>解析成svg。

3.解决方案

方案一(不推荐):
在main.ts中全局注册这两个组件

import { Expand, Fold } from "@element-plus/icons-vue";
app.component("Expand", Expand);
app.component("Fold", Fold);

使用:

<component
        :is="settingStore.collapsed ? 'Fold' : 'Expand'"
      ></component>

方案二:
h函数:h函数是用来创建虚拟节点(vnode)的
1.定义一个数组来存放这两个需要动态渲染的图标

let collaspsedIcons = [
  {
    name: "Fold",
    icon: () => h(),
  },
  {
    name: "Expand",
    icon: () => h(),
  },
];

2.引入需要动态渲染的图标,并分别放入h函数

import Fold from "~icons/ep/fold";
import Expand from "~icons/ep/expand";

tips:为什么是这样的路径?
可以先在其他地方写<IEpFold/>,然后ctrl+左键,就能进入components.d.ts这个存放组件的文件,这里就有路径,复制过来即可。
在这里插入图片描述
3.新建type.ts,用来给collaspsedIcons数组定义 类型(也可以不定义name)

import type { Component } from "vue";
export interface CollaspsedIcon {
  name: string;
  icon: Component;
}

此处icon的值就是一个component组件
4.补全1中的代码

import Fold from "~icons/ep/fold";
import Expand from "~icons/ep/expand";
import { CollaspsedIcon } from "./type.ts";

let collaspsedIcons: Array<CollaspsedIcon> = [
  {
    name: "Fold",
    icon: () => h(Fold),
  },
  {
    name: "Expand",
    icon: () => h(Expand),
  },
];

5.进行动态渲染:

<el-icon @click="changeIcon" size="18">
      <component
        :is="
          settingStore.collapsed
            ? collaspsedIcons[0].icon
            : collaspsedIcons[1].icon
        "
      ></component>
    </el-icon>

参考文章:
element中自动引入icon

解决方案一的全局注册

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值