暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Vue3 + Vite:SVG图标(unplugin-icons)

Nephilim 2024-07-02
449

Tips:一些记录,一些笔记



2024/07/01

MONDAY

After work, first entertainment.

先工作,后娱乐。




01

Vue3项目中使用SVG


在前面,我们通过「vite-plugin-svg-icons」实现过一种SVG的方案:

Vue.JS:引入SVG资源更好的方式


今天,我们介绍一下另一种SVG的图标的解决方案,通过「unplugin-icons」实现。


02

安装


首先,通过PNPM安装相关的依赖包:

    (base) adamhuan@Leviathan beast-harbor-vite % pnpm list
    Legend: production dependency, optional only, dev only


    beast-harbor-vite@0.0.0 Users/adamhuan/beast-harbor/beast-harbor-vite (PRIVATE)


    dependencies:
    @vueuse/core 10.11.0
    pinia 2.1.7
    vue 3.4.31
    vue-router 4.4.0


    devDependencies:
    @arco-design/web-vue 2.55.3 @vue/eslint-config-typescript 13.0.0 unplugin-auto-import 0.17.6
    @rushstack/eslint-patch 1.10.3 @vue/tsconfig 0.5.1 unplugin-vue-components 0.27.2
    @tsconfig/node20 20.1.4 eslint 8.57.0 vite 5.3.2
    @types/node 20.14.9 eslint-plugin-vue 9.26.0 vite-plugin-svg-icons 2.0.1
    @vitejs/plugin-vue 5.0.5 npm-run-all2 6.2.0 vue-tsc 2.0.24
    @vitejs/plugin-vue-jsx 4.0.0 prettier 3.3.2
    @vue/eslint-config-prettier 9.0.0 typescript 5.4.5
    (base) adamhuan@Leviathan beast-harbor-vite %
    (base) adamhuan@Leviathan beast-harbor-vite % pnpm add -D unplugin-icons
     WARN  10 deprecated subdependencies found: @humanwhocodes/config-array@0.11.14, @humanwhocodes/object-schema@2.0.3, glob@7.2.3, inflight@1.0.6, resolve-url@0.2.1, rimraf@3.0.2, source-map-resolve@0.5.3, source-map-url@0.4.1, stable@0.1.8, urix@0.1.0
    Packages: +20
    ++++++++++++++++++++
    Progress: resolved 578, reused 541, downloaded 0, added 20, done


    devDependencies:
    + unplugin-icons 0.19.0


    Done in 2.3s
    (base) adamhuan@Leviathan beast-harbor-vite %
    (base) adamhuan@Leviathan beast-harbor-vite % pnpm list | grep unplugin-icons
    unplugin-icons 0.19.0
    (base) adamhuan@Leviathan beast-harbor-vite %


    03

    配置


    一、文件「vite.config.ts」


    首先,导入:


    然后,在「plugin」中进行配置:

    可以看到,上面只配置了两个配置项「compiler autoInstall」


    它的完整配置项如下:

      Icons({
      scale: 1.2, Scale of icons against 1em
      defaultStyle: '', Style apply to icons
      defaultClass: '', Class names apply to icons
      compiler: null, 'vue2', 'vue3', 'jsx'
      jsx: 'react' 'react' or 'preact'
      })
      scale缩放
      compiler
      编译方式
      defaultClass
      默认类名
      defaultStyle
      默认样式
      jsx
      JSX支持
      autoInstall
      自动加载


      这时候,该文件的完整内容如下:

        import { fileURLToPath, URL } from 'node:url'


        import { defineConfig, loadEnv } from 'vite'
        import vue from '@vitejs/plugin-vue'
        import vueJsx from '@vitejs/plugin-vue-jsx'


        // 按需导入
        import AutoImport from 'unplugin-auto-import/vite'
        import Components from 'unplugin-vue-components/vite'
        import {
        ArcoResolver,
        VueUseComponentsResolver,
        VueUseDirectiveResolver
        } from 'unplugin-vue-components/resolvers'


        // 图标(vite-plugin-svg-icons)
        import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'


        // 图标(unplugin-icons)
        import Icons from 'unplugin-icons/vite'


        // https://vitejs.dev/config/
        export default defineConfig(({ mode }) => {
        const env = loadEnv(mode, process.cwd(), '')


        return {
        plugins: [
        vue(),
        vueJsx(),
        createSvgIconsPlugin({
        iconDirs: [fileURLToPath(new URL('./src/assets/icons', import.meta.url))],
        symbolId: 'icon-[dir]-[name]'
        }),
        Icons({
        compiler: 'vue3',
        autoInstall: true
        }),
        AutoImport({
        需要去解析的文件
        include: [
        \.[tj]sx?$/, .ts, .tsx, .js, .jsx
        \.vue$/,
        \.vue\?vue/, .vue
        \.md$/ .md
        ],
        imports 指定自动引入的包位置(名)
        imports: ['vue', 'pinia', 'vue-router', '@vueuse/core'],
        生成相应的自动导入json文件。
        eslintrc: {
        启用
        enabled: true,
        生成自动导入json文件位置
        filepath: './.eslintrc-auto-import.json',
        全局属性值
        globalsPropValue: true
        },
        resolvers: [ArcoResolver()]
        }),
        Components({
        imports 指定组件所在目录,默认为 src/components
        dirs: ['src/components/', 'src/view/'],
        需要去解析的文件
        include: [/\.vue$/, \.vue\?vue/, \.md$/],
        resolvers: [
        ArcoResolver({
        sideEffect: true
        }),
        VueUseComponentsResolver(),
        VueUseDirectiveResolver()
        ]
        })
        ],
        resolve: {
        alias: {
        '@': fileURLToPath(new URL('./src', import.meta.url))
        }
        },
        css: {
        preprocessorOptions: {
        scss: {
        prependData: ``,
        additionalData: `
        自定义字体样式
        @use "@/styles/fonts/fonts.scss" as *;
        `
        }
        }
        },
        server: {
        host: '0.0.0.0',
        port: 4000
        }
        }
        })



        二、Icon图标自动引入(不需要下载图标库,系统会自动按需下载


        配置「自动引入」的意义在于:不需要完整的下载图标库,系统会自动的按需进行下载


        如下所示:

        下面开始配置「自动引入」:


        Icon图标的自动引入需要配合「unplugin-vue-components」组件一起使用,才可生效。


        「unplugin-vue-components」的Github官方网站:

        https://github.com/unplugin/unplugin-vue-components


        继续配置「vite.config.ts」文件:


        这个时候,该文件的完整内容:

          import { fileURLToPath, URL } from 'node:url'


          import { defineConfig, loadEnv } from 'vite'
          import vue from '@vitejs/plugin-vue'
          import vueJsx from '@vitejs/plugin-vue-jsx'


          // 按需导入
          import AutoImport from 'unplugin-auto-import/vite'
          import Components from 'unplugin-vue-components/vite'
          import {
          ArcoResolver,
          VueUseComponentsResolver,
          VueUseDirectiveResolver
          } from 'unplugin-vue-components/resolvers'


          // 图标(vite-plugin-svg-icons)
          import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'


          // 图标(unplugin-icons)
          import Icons from 'unplugin-icons/vite'
          import IconsResolver from 'unplugin-icons/resolver'


          // https://vitejs.dev/config/
          export default defineConfig(({ mode }) => {
          const env = loadEnv(mode, process.cwd(), '')


          return {
          plugins: [
          vue(),
          vueJsx(),
          createSvgIconsPlugin({
          iconDirs: [fileURLToPath(new URL('./src/assets/icons', import.meta.url))],
          symbolId: 'icon-[dir]-[name]'
          }),
          Icons({
          // scale: 1, // 缩放
          compiler: 'vue3', // 编译方式
          // defaultClass: '', // 默认类名
          // defaultStyle: '', // 默认样式
          autoInstall: true
          // jsx: 'react' // jsx支持
          }),
          AutoImport({
          // 需要去解析的文件
          include: [
          /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
          /\.vue$/,
          /\.vue\?vue/, // .vue
          /\.md$/ // .md
          ],
          // imports 指定自动引入的包位置(名)
          imports: ['vue', 'pinia', 'vue-router', '@vueuse/core'],
          // 生成相应的自动导入json文件。
          eslintrc: {
          // 启用
          enabled: true,
          // 生成自动导入json文件位置
          filepath: './.eslintrc-auto-import.json',
          // 全局属性值
          globalsPropValue: true
          },
          resolvers: [ArcoResolver()]
          }),
          Components({
          // imports 指定组件所在目录,默认为 src/components
          dirs: ['src/components/', 'src/view/'],
          // 需要去解析的文件
          include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
          resolvers: [
          ArcoResolver({
          sideEffect: true
          }),
          VueUseComponentsResolver(),
          VueUseDirectiveResolver(),
          IconsResolver({
          prefix: 'icon', // 自动引入的Icon组件统一前缀,默认为 i,设置false为不需要前缀
          // {prefix}-{collection}-{icon} 使用组件解析器时,您必须遵循名称转换才能正确推断图标。
          // alias: { park: 'icon-park' } 集合的别名
          enabledCollections: ['ep'] // 这是可选的,默认启用 Iconify
          })
          ]
          })
          ],
          resolve: {
          alias: {
          '@': fileURLToPath(new URL('./src', import.meta.url))
          }
          },
          css: {
          preprocessorOptions: {
          scss: {
          prependData: ``,
          additionalData: `
          // 自定义字体样式
          @use "@/styles/fonts/fonts.scss" as *;
          `
          }
          }
          },
          server: {
          host: '0.0.0.0',
          port: 4000
          }
          }
          })



          04

          在哪里找图标?


          该工具(unplugin-icons)所引用的图标,都可以在以下的几个网站上找到:

          一、https://icones.netlify.app/

          它的Github官方网站:

          https://github.com/antfu-collective/icones


          二、https://icon-sets.iconify.design



          05

          引入图标(https://icones.netlify.app/)


          首先,在网站上找到你希望引入的图标:

          https://icones.netlify.app/

          当你复制「Iconify」

            <span class="iconify" data-icon="material-symbols:10k" data-inline="false"></span>

            当你复制「Unplugin Icons」

              import MaterialSymbols10k from '~icons/material-symbols/10k'

              当你点击标题旁边的复制的时候:

                material-symbols:10k


                然后,在前端页面中使用:

                完整内容:

                  <template>
                  <div class="about">
                  <h1>This is an about page</h1>
                  <svg-icon class="icon" size="50" name="电池"></svg-icon>
                  <svg-icon class="icon" size="50" name="数据"></svg-icon>
                  <svg-icon class="icon" size="50" name="图片"></svg-icon>


                  <div>你好世界</div>
                  <a-space>
                  <a-button type="primary" size="mini" @click="handleClick">Mini</a-button>
                  <a-button type="primary" size="small">Small</a-button>
                  <a-button type="primary">Medium</a-button>
                  <a-button type="primary" size="large">Large</a-button>
                  </a-space>
                  <HelloMessage />
                  <a-space>
                  <IconMaterialSymbols10k />
                  <icon-material-symbols-10k />
                  </a-space>
                  </div>
                  </template>


                  <script setup>
                  const handleClick = () => {
                  AMessage.info('按钮被点击了')
                  }
                  </script>


                  <style>
                  @media (min-width: 1024px) {
                  .about {
                  min-height: 100vh;
                  display: flex;
                  align-items: center;
                  }
                  }
                  </style>



                  这时候的页面效果:


                  06

                  引入图标(https://icon-sets.iconify.design/)


                  比方说,我们要引入这个图标:

                  页面中引入:


                  这时候的页面效果:

                  可以看到,地球的图标已经引入成功了。


                  这个时候,该文件的完整内容如下:

                    <template>
                    <div class="about">
                    <h1>This is an about page</h1>
                    <svg-icon class="icon" size="50" name="电池"></svg-icon>
                    <svg-icon class="icon" size="50" name="数据"></svg-icon>
                    <svg-icon class="icon" size="50" name="图片"></svg-icon>


                    <div>你好世界</div>
                    <a-space>
                    <a-button type="primary" size="mini" @click="handleClick">Mini</a-button>
                    <a-button type="primary" size="small">Small</a-button>
                    <a-button type="primary">Medium</a-button>
                    <a-button type="primary" size="large">Large</a-button>
                    </a-space>
                    <HelloMessage />
                    <a-space>
                    <IconMaterialSymbols10k />
                    <icon-material-symbols-10k />
                    <IconMdiEarth />
                    <icon-mdi-earth />
                    </a-space>
                    </div>
                    </template>


                    <script setup>
                    const handleClick = () => {
                    AMessage.info('按钮被点击了')
                    }
                    </script>


                    <style>
                    @media (min-width: 1024px) {
                    .about {
                    min-height: 100vh;
                    display: flex;
                    align-items: center;
                    }
                    }
                    </style>



                    07

                    终了


                    至此,以「unplugin-icons」的方式引入图标的细节就全部描述完了。





                    END




                    温馨提示



                    如果你喜欢本文,请分享到朋友圈,想要获得更多信息,请关注我。


                    文章转载自Nephilim,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                    评论