赞
踩
对于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上颜色就行了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。