Iconify图标离线使用 (在vben-admin框架中离线使用)

  1. 在线图标库iconify 的离线使用
  2. 在vben-admin框架中使用离线Iconify图标库

一、Iconify图标库离线使用

1. 安装依赖

npm install @iconify/json @iconify/vue
# 如果是 Vue 2 项目,还需要安装 @vue/composition-api
npm install @vue/composition-api  # Vue 2 专用

2. 提取图标数据

// 从 @iconify/json 中提取特定图标集的 JSON 数据(例如 Material Design Icons):

// 示例:src/utils/icons.js
import { addCollection } from '@iconify/vue';
import mdiData from '@iconify/json/json/mdi.json'; // 路径可能因版本变化

// 加载整个图标集
addCollection(mdiData);

// 或按需加载单个图标(推荐减少体积)
const { icons } = mdiData;
addCollection({
  prefix: 'mdi',
  icons: {
    // 选择需要的图标
    account: icons.account,
    home: icons.home,
    // ...
  }
});

3. 全局注册 Icon 组件


在 Vue 入口文件(如 main.js)中注册组件:

// main.js
import { createApp } from 'vue';
import App from './App.vue';
import { Icon } from '@iconify/vue';
import './utils/icons'; // 导入图标数据初始化

const app = createApp(App);
app.component('Icon', Icon); // 全局注册组件
app.mount('#app');

4. 在组件中使用图标


<template>
  <!-- 使用图标 -->
  <Icon icon="mdi:account" />
  <Icon icon="mdi:home" :inline="true" /> <!-- inline 模式 -->
</template>

5. 按需加载优化


若需进一步优化体积,可动态加载图标:

// utils/icons.js
import { addIcon } from '@iconify/vue';

// 动态加载单个图标
export function loadIcon(iconName) {
  import(`@iconify/json/json/mdi.json`).then((mdiData) => {
    const iconData = mdiData.icons[iconName];
    addIcon(`mdi:${iconName}`, iconData);
  });
}

// 在组件中使用:
// 在需要的地方调用 loadIcon('account') 预加载

6. 构建工具配置

确保构建工具(Vite/Webpack)正确处理 JSON 文件:

Vite 配置(vite.config.js)
javascript
复制
export default {
  assetsInclude: ['**/*.json'],
};
Vue CLI/Webpack 配置
javascript
复制
// vue.config.js
module.exports = {
  chainWebpack: (config) => {
    config.module
      .rule('json')
      .test(/\.json$/)
      .type('javascript/auto')
      .use('json-loader')
      .loader('json-loader');
  }
};

二、在vben-admin中使用离线图标Iconify

1. 下载依赖

npm install @iconify/json@2.2.224
npm install @purge-icons/generated@^0.9.0
npm install @iconify/json @iconify/vue
2 . 提取图标数据
// 从 @iconify/json 中提取特定图标集的 JSON 数据(例如 Material Design Icons):

示例: src\settings\iconSettings.ts
import { addCollection } from 'iconify-icon';

import antDesignIcons from '@iconify/json/json/ant-design.json';
import bpmnIcons from '@iconify/json/json/bpmn.json';
import bxIcons from '@iconify/json/json/bx.json';
import ionIcons from '@iconify/json/json/ion.json';
import lineMdIcons from '@iconify/json/json/line-md.json';
import mdiIcons from '@iconify/json/json/mdi.json';
import vaadinIcons from '@iconify/json/json/vaadin.json';

// 注册图标
addCollection(antDesignIcons);
addCollection(bpmnIcons);
addCollection(bxIcons);
addCollection(ionIcons);
addCollection(lineMdIcons);
addCollection(mdiIcons);
addCollection(vaadinIcons);

3. 【Icon.vue】(完整代码)

src\components\Icon\src\Icon.vue


<template>
  <SvgIcon
    :size="size"
    :name="getSvgIcon"
    v-if="isSvgIcon"
    :class="[$attrs.class, 'anticon']"
    :spin="spin"
  />
  <span
    v-else
    :class="[$attrs.class, 'app-iconify anticon', spin && 'app-iconify-spin']"
    :style="getWrapStyle"
  >
    <iconify-icon
      :icon="icon"
      :rotate="`${rotate}deg`"
      :width="size"
      :style="{
        color: color,
      }"
    />
  </span>
</template>
<script lang="ts">
  import type { PropType } from 'vue';
  import {
    defineComponent,
    ref,
    watch,
    onMounted,
    nextTick,
    unref,
    computed,
    CSSProperties,
  } from 'vue';
  import SvgIcon from './SvgIcon.vue';
  import Iconify from '@purge-icons/generated';
  import { isString } from '/@/utils/is';
  import { propTypes } from '/@/utils/propTypes';

  const SVG_END_WITH_FLAG = '|svg';
  export default defineComponent({
    name: 'Icon',
    components: { SvgIcon },
    props: {
      // icon name
      icon: propTypes.string,
      // icon color
      color: propTypes.string,
      // icon size
      size: {
        type: [String, Number] as PropType<string | number>,
        default: 16,
      },
      rotate: {
        type: [String, Number],
        default: '0',
        required: false,
      },
      spin: propTypes.bool.def(false),
      prefix: propTypes.string.def(''),
    },
    setup(props) {
      const elRef = ref<ElRef>(null);

      const isSvgIcon = computed(() => props.icon?.endsWith(SVG_END_WITH_FLAG));
      const getSvgIcon = computed(() => props.icon.replace(SVG_END_WITH_FLAG, ''));
      const getIconRef = computed(() => `${props.prefix ? props.prefix + ':' : ''}${props.icon}`);

      const update = async () => {
        if (unref(isSvgIcon)) return;

        const el = unref(elRef);
        if (!el) return;

        await nextTick();
        const icon = unref(getIconRef);
        if (!icon) return;

        const svg = Iconify.renderSVG(icon, {});
        if (svg) {
          el.textContent = '';
          el.appendChild(svg);
        } else {
          const span = document.createElement('span');
          span.className = 'iconify';
          span.dataset.icon = icon;
          el.textContent = '';
          el.appendChild(span);
        }
      };

      const getWrapStyle = computed((): CSSProperties => {
        const { size, color } = props;
        let fs = size;
        if (isString(size)) {
          fs = parseInt(size, 10);
        }

        return {
          fontSize: `${fs}px`,
          color: color,
          display: 'inline-flex',
        };
      });

      watch(() => props.icon, update, { flush: 'post' });

      onMounted(update);

      return { elRef, getWrapStyle, isSvgIcon, getSvgIcon };
    },
  });
</script>
<style lang="less">
  .app-iconify {
    display: inline-block;
    // vertical-align: middle;

    &-spin {
      svg {
        animation: loadingCircle 1s infinite linear;
      }
    }
  }

  span.iconify {
    display: block;
    min-width: 1em;
    min-height: 1em;
    background-color: @iconify-bg-color;
    border-radius: 100%;
  }
</style>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值