icon解决方案(iconify),基于unplugin-icons封装通用icon组件

前言:

        对于icon,前端的第一反应就是采用iconfont来做,对于多数场景当然是没有问题的,甚至后续项目中出现自定义icon只需要ui将设计传到iconfont平台就行了,但是毕竟还是经过了第三方平台的,所以我采用了iconify方案

需求:

        我现在的项目之前是用的MDI的图标库,后续因为ui陆续将icon设计出来了,所以也需要上传我们自己的自定义图标,所以需要兼容两种情况

步骤:

        1.选用插件:unplugin-icons与unplugin-auto-import/vite插件----通过插件实现图标的自动导入和Vue组件的按需导入,无需手动导入图标,直接在模板中使用图标名称即可。这种方式更加自动化和便捷,但需要配置相应的插件和解析器。

          相关配置(vite.config.js)


// icon相关插件
import AutoImport from 'unplugin-auto-import/vite'
import Icons from 'unplugin-icons/vite'
// icon 自动引入解析器
import IconsResolver from 'unplugin-icons/resolver'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { FileSystemIconLoader } from 'unplugin-icons/loaders'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      imports: ['vue'],
      resolvers: [ElementPlusResolver(),IconsResolver({
        componentPrefix: "icon",
        enabledCollections: ["datalink", "mdi"],
      })],
    }),
    Icons({
      // 默认的比例为1
      scale:1,
      compiler: 'vue3',// 指定编译器
      autoInstall: true,// 自动安装(如果你用了element的icon但你没有下载对应的.json文件,它会自动帮你下载,如果你没这个需求,就不用设置)
      // 配置自定义的图标(里面直接放svg就行了)
      customCollections: {
        datalink: FileSystemIconLoader('./src/components/icon-iconify/icon-svg')
      }
    }),
  ]
})

配置完成后,就可以在项目中直接使用了,插件可以自动的按需加载图标,不需要手动导入

<template>
  <h1>
    icon方案测试1
  </h1>
  <!--使用其他的icon图标集,这里展示的element puls的(需要配置)-->
  <IconEpCellphone></IconEpCellphone>
  <!--使用自定义的svg图-->
  <IconDatalinkE/>
  <icon-mdi-bowl></icon-mdi-bowl>

</template>

问题:

        但是接下来就引出一个新的问题了,如果我使用不同的图标库,这个使用图标组件的名称都有所区别比如说MDI:就是icon-mdi-xxxx,element puls: 就是icon-ep-xxxx 更别说我们的自定义图标了,所以为了统一,最好封装一个组件,这样我们使用时就比较统一了(接下来也就是本篇文章的重点)

        在github上,如果你去留意多数人提的问题,会发现,很多人都在询问能否通过动态的方法去生成icon图标呢,作者的统一回答都是 NO,原因是:

        由于unplugin-vue-components的工作机制,无法从动态字符串推断组件。 (unplugin-icons仅在构建时解析图标),如果你在运行后尝试动态生成,那是没有作用的

 相关问题:

Unable to use <Component :is="" · Issue #260 · unplugin/unplugin-icons · GitHub

<!-- 通过is切换是不行的 -->
  <template #title>
    <el-icon v-if="menu.meta.icon"><component :is="menu.meta.icon"/></el-icon>
    <span>{{ menu.meta.title }}</span>
  </template>
  <menu-item v-for="(item, key) in menu.children" :key="key" :menu="item" :basePath="pathResolve" />
</el-sub-menu>

   

解决:

        github上也有人提出对应的解决方案(提前将要使用的icon准备好就行了),这样就是在构建时完成了(如果还是不行,大概率是缺少unplugin-auto-import/vite插件的配置导致的),要实现下方的功能

https://github.com/unplugin/unplugin-icons/issues/5

<template>
  <div class="p-icon" :class="[iconColor]">
    <component :is="icon" :width="iconSize" :height="iconSize"></component>
  </div>
</template>

<style lang="less">
.p-icon {
  svg {
    fill: red;
  }
  &.p-icon-primary {
    svg {
      fill: red;
    }
  }
}
</style>

<script setup>
import { computed } from 'vue';

const props = defineProps({
  icon: {
    type: String,
    default: '',
  },
  size: {
    type: [Number, String],
    default: 20,
  },
  primary: {
    type: Boolean,
    default: false,
  },
});

// 自定义图标集(:的右边部分就是插件的使用,根据你的配置名称可能会有所不同需要注意)
const items = {
  'jellyfish': IconDatalinkJellyfish,
  'arrow-down': IconDatalinkArrowDown,
  'arrow-left': IconDatalinkArrowLeft,
  'arrow-right': IconDatalinkArrowRight,
};

const icon = computed(() => {
  const iconName = props.icon.split('icon-')[1];
  if (items[iconName]) {
    return items[iconName];
  }
  // 当图标不存在时,默认展示
  return items['jellyfish'];
});

const iconSize = computed(() => {
  return props.size;
});

const iconColor = computed(() => {
  if (props.primary) {
    console.log('是primary');
    return 'p-icon-primary';
  }
  return '';
});
</script>

小知识点:

        如果你试图改变svg的颜色,你发现改变不了,你可以去仔细看看,你的svg文件,内部是否存在一个默认fill属性,你需要将其删除,通过css给svg上颜色就行了

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值