前端开发小技巧 - 【TS + Vue】 - 将 svg格式 的 图片 打包成 svg地图

前言

  • 如果在一个项目中有很多png、jpg等等格式的图片,我们一般会将这些零散的图片合成一张 精灵图 ,通过背景图片的定位去使用不同的图片;
  • 如果一个项目使用到的图标绝大部分是svg格式的,为了简化使用,我们应该怎么办呢?
    • 下面就来说道说道;

一、svg简介

  • 什么是SVG
    • SVG 指可伸缩矢量图形(Scalable Vector Graphics);
    • SVG 用来定义网络的基于矢量的图形;
    • SVG 使用 XML 格式定义图形;
    • SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失;
    • SVG 是万维网联盟的标准;
    • SVG 与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体;
  • SVG2003年1月14日 成为 W3C 推荐标准;
  • svg格式的图片:
    • 它是 xml格式的;
  • 如果一个项目中有很多的svg格式的图片,我们可以打包成 svg地图 对不同的svg格式的图片进行使用;

二、打包成svg地图

  • 简单来说,svg地图 就是另一种形式的 精灵图

  • svg格式的图片打包成 svg地图 需要使用到 vite-plugin-svg-icons 这个插件;

  • 下载

    • pnpm add vite-plugin-svg-icons -D
  • 配置

    • vite-plugin-svg-icons官方中文文档;

    • 目标文件:

      • vite.config.ts
      ts 复制代码
      // 导入插件
      import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
      // 导入 path(帮助我们生成路径)
      import path from 'path'
      
      export default () => {
        return {
          plugins: [
            // ... 其他的插件配置
            
            // 使用插件
            createSvgIconsPlugin({
              // 指定需要缓存的图标文件夹 - 'src/icons'
              // 就是说我们需要生成 svg地图 的所有 svg图标 在哪个文件夹下
              // 我是放在 src/icons 下面,大家根据自己的文件夹写就可以了;
              iconDirs: [path.resolve(process.cwd(), 'src/icons')],
            })
            
            // ... 其他的插件配置
          ],
        }
      }
      • 我所有的svg图标都放在这块:
  • main.ts中注入脚本

    ts 复制代码
    // 导入 svg地图
    import 'virtual:svg-icons-register';

三、基础使用

  • 打包成svg地图之后,所有的svg格式图片的代码合在一块了;

  • 合在一块之后,每个svg标签上都会有个id属性;

  • 使用步骤

    1. 在需要使用svg图片的地方,先添加一个 svg标签
    2. svg标签 内部再使用 use标签;
    3. use标签的 href 属性 的属性值设置为 #icon-存放当前使用svg的文件夹-svg名字(不带.svg后缀) 的格式即可;
  • 注意

    • use标签的href属性赋值的时候#icon-是固定写法;
  • 示例:

    html 复制代码
    <svg aria-hidden="true">
        <use href="#icon-consult-alipay"></use>
    </svg>
  • 我们可以看到,所有的svg都被导入进来了,并且都是有id属性的,所有的id属性都带有icon-的前缀;

四、封装组件

4.1 封装组件

  • 组件所在位置

    • src/components/SvgIcon/index.vue
  • 封装组件

    html 复制代码
    <script setup lang="ts" name="SvgIcon">
    // 声明props
    withDefaults(
      defineProps<{
        name: string;
        width?: string;
        height?: string;
      }>(),
      {
        // 默认大小大家可以根据自己的需要设置
        width: '1em',
        height: '1em'
      }
    );
    </script>
    
    <template>
      <svg aria-hidden="true" class="svg-icon">
        <use :href="`#icon-${name}`" />
      </svg>
    </template>
    
    <style scoped lang="scss">
    /* 动态设置样式 */
    .svg-icon {
      width: v-bind(width);
      height: v-bind(height);
    }
    </style>

4.2 给组件添加类型

  • 目标文件

    • src/types/components.d.ts
  • 代码:

    ts 复制代码
    // 方式一
    import SvgIcon from '@/components/SvgIcon';
    
    // 固定写法
    declare module 'vue' {
      interface GloablComponents {
        // 组件名称: typeof 组件;
        // typeof 操作符能得到 组件的类型再给组件
        SvgIcon: typrof SvgIcon
      }
    }
    
    // 方式二
    declare module 'vue' {
      interface GlobalComponents {
        SvgIcon: typeof import('@/components/SvgIcon');
      }
    }
相关推荐
轻口味1 小时前
命名空间与模块化概述
开发语言·前端·javascript
前端小小王2 小时前
React Hooks
前端·javascript·react.js
迷途小码农零零发2 小时前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀2 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
旭东怪3 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
yg_小小程序员3 小时前
vue3中使用vuedraggable实现拖拽
typescript·vue
ekskef_sef4 小时前
32岁前端干了8年,是继续做前端开发,还是转其它工作
前端
高山我梦口香糖4 小时前
[react 3种方法] 获取ant组件ref用ts如何定义?
typescript·react
sunshine6414 小时前
【CSS】实现tag选中对钩样式
前端·css·css3