前端开发小技巧 - 【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');
      }
    }
相关推荐
秦jh_1 小时前
【Linux】多线程(概念,控制)
linux·运维·前端
蜗牛快跑2131 小时前
面向对象编程 vs 函数式编程
前端·函数式编程·面向对象编程
Dread_lxy1 小时前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js
涔溪2 小时前
Ecmascript(ES)标准
前端·elasticsearch·ecmascript
榴莲千丞2 小时前
第8章利用CSS制作导航菜单
前端·css
奔跑草-2 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
羡与2 小时前
echarts-gl 3D柱状图配置
前端·javascript·echarts
guokanglun2 小时前
CSS样式实现3D效果
前端·css·3d
咔咔库奇2 小时前
ES6进阶知识一
前端·ecmascript·es6
渗透测试老鸟-九青3 小时前
通过投毒Bingbot索引挖掘必应中的存储型XSS
服务器·前端·javascript·安全·web安全·缓存·xss