在Vue3项目中使用svg-sprite-loader

news2025/1/8 15:08:24
1.普通的svg图片使用方式
1.1 路径引入
  • 正常我们会把项目中的静态资源放在指定的一个目录,例如assets,使用起来就像
<img src="../assets/svgicons/about.svg" />
1.2封装组件使用
  • 显然上面的这种方法在项目开发中不太适用,每次都需要通过路径引用
  • 此次封装的目的就是简化写法,以更加简洁的方式引用图标并且具备更好的复用性
  • 封装后使用如下:
 
<svg-Icon name="user"></SvgIcon>
//1. SvgIcon为全局组件,name表示要使用的svg图标名称
 
//2. user.svg图标存放于icons/svg目录下(路径不固定存放,跟随自己需求)
 2.依赖安装与loader配置
2.1下载依赖 
  • 根据自己项目的版本需求,下载所兼容的svg-sprite-loader的版本
npm i svg-sprite-loader -D
// 或是
yarn add svg-sprite-loader -D
2.2 loader配置
  • 打开vue.config.js文件,在chainWebpack函数中新增配置
  • 这里有两种写法
2.2.1 方式一
  • 如果你整个项目中的svg文件都希望使用雪碧图的方式进行处理,那么这么写
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  chainWebpack: (config) => {
    const svgRule = config.module.rule('svg')
    svgRule.uses.clear()
    // 添加要替换的 loader
    svgRule.use('svg-sprite-loader')
           .loader('svg-sprite-loader')
           .options({symbolId: 'icon-[name]'})
  }
})
2.2.2 方式二
  • 或者说你只希望指定目录下的svg文件被svg-sprite-loader处理,其他的还是使用webpack5默认的svg处理方式,那么这么写
//这行代码引入了 Node.js 的 path 模块,该模块提供了用于处理文件路径的实用工具方法,后续会用于拼接路径等操作。
const path = require('path')
//定义了一个resolve的函数,它接收一个参数dir
//函数的功能是使用,path.join方法将当前模块所在目录和传入的dir参数所代表的路径进行拼接,最终返回拼接后的完整路径,这个函数常用于处理相对路径,使其更准确指向项目内的特定目录
//——dirname是是一个特殊变量。表示当前执行脚本所在的目录的绝对路径,它是一个全局变量,可以在任何地方使用,用于获取当前模块的文件所在的目录路径,
//为什么使用——而不使用.:“使用.来获取当前文件的路径可能导致路径不准确,因为.代表当前目录,可能会随着当前文件的深度变化而变化,而使用——dirname则可以确保获取到当前文件的真实路径,不会随着文件深度变化”
 function resolve(dir) {
    return path.join(__dirname, dir)
 }

    /**
      * chainWebpack对象中的内容介绍
      * 这里的config是webpack的链条式操作配置对象,下面通过调用它的一系列方法来修改webpack的模块处理规则等配置内容
    */
  chainWebpack(config) {

    // 设置 svg-sprite-loader
    // config 为 webpack 配置对象
    // config.module 表示创建一个具名规则,以后用来修改规则
    /**
      * 这部分代码开始配置 Webpack 对 svg 文件的处理规则。
      * 首先通过 config.module.rule('svg') 创建了一个名为 svg 的规则,后续的操作都是针对这个规则来进行的。
      * .exclude.add(resolve('src/icons')) 表示对于 Webpack 处理模块时,
      * 当遇到 src/icons 目录下的 svg 文件时,要排除它们,不应用当前这个 svg 规则去处理(通常是因为后面会针对这个目录下的 svg 文件有特殊的处理规则设置),最后 .end() 用于结束当前这一步规则的链式操作,回到上一级配置链。
    */
    config.module
      // 规则

      // 在 module 配置的规则集合里,通过调用 rule 方法并传入 'svg' 字符串来开始定义针对 .svg 文件类型的模块处理规则。后续会在这条规则上继续添加更多的配置,比如排除某些目录下的 .svg 文件不使用这条规则处理等。
      .rule('svg')
      // 忽略
      // 在刚才定义的 .svg 文件模块处理规则里,调用 exclude 方法,它用于指定哪些目录下的对应文件类型(这里就是 .svg 文件)不需要应用这条规则去处理。这里调用了之前定义的 resolve 函数,传入 'src/icons' 参数,也就是将 src/icons 目录对应的绝对路径添加到排除列表中,意味着 src/icons 目录下的 .svg 文件不会按照这条常规的 .svg 模块处理规则去加载。
      .exclude.add(resolve('src/icons'))
      // 结束
      .end()
    // config.module 表示创建一个具名规则,以后用来修改规则
    config.module
      // 规则
      // 创建一个新的名为 'icons' 的模块处理规则,虽然也是针对 .svg 文件,但和前面常规的 .svg 规则区分开,这里将用于配置 src/icons 目录下 .svg 文件的特定加载方式等。
      .rule('icons')
      // 正则,解析 .svg 格式文件
      // 在这个新的 'icons' 规则里,通过 test 方法指定这条规则应用的文件类型匹配模式,这里传入的正则表达式 /\.svg$/ 表示匹配以 .svg 为后缀的文件,也就是明确这条规则是针对 .svg 文件的,和前面规则名称里的意图相呼应,专门来处理 src/icons 目录下符合此类型的文件
      .test(/\.svg$/)
      // 解析的文件
      // 调用 include 方法并传入通过 resolve 函数获取的 src/icons 目录的绝对路径,include 方法的作用是指定哪些目录下的文件要应用这条规则进行处理,这里就明确了只有 src/icons 目录下的文件(结合前面的 .test 匹配 .svg 文件类型,实际就是 src/icons 目录下的 .svg 文件)才应用这条特殊的 'icons' 规则来处理。
      .include.add(resolve('src/icons'))
      // 结束
      .end()
      // 新增了一个解析的loader
      // 在这个 'icons' 规则里,调用 use 方法并传入 'svg-sprite-loader',这是指定使用 svg-sprite-loader 这个 Webpack loader 来处理符合这条规则的文件(即 src/icons 目录下的 .svg 文件)。loader 是 Webpack 中用于对不同类型文件进行转换等操作的工具,svg-sprite-loader 可以将多个 .svg 文件合并为一个雪碧图(Sprite),便于在网页中更高效地使用图标等 SVG 资源。
      .use('svg-sprite-loader')
      // 具体的loader
      // 再次明确指定要使用的 loader 名称为 svg-sprite-loader,这里其实和前面的 .use('svg-sprite-loader') 是相关联且作用基本一致的,是在链式配置中进一步确定使用的加载器信息,有些情况下这种重复指定可能是遵循特定配置语法要求或者为了更清晰明确加载器的使用情况。
      .loader('svg-sprite-loader')
      // loader 的配置
      .options({
        // 这是 options 对象里的一个配置项,对于 svg-sprite-loader 来说,symbolId 配置用于指定生成的雪碧图中每个 <symbol> 元素(SVG 里用于定义可复用图形元素的标签)的 id 属性的命名规则。这里设置为 'icon-[name]',意味着每个 <symbol> 元素的 id 会基于 SVG 文件的原名([name] 会被替换为实际文件名)来生成,格式如 icon-文件名,方便在 HTML 等地方通过这个 id 来引用对应的 SVG 图标元素。
        symbolId: 'icon-[name]'
      })
      // 结束
      .end()
  }
}



/**
 *
 两个规则的区别
   1. 适用范围不同
    常规 .svg 规则(rule('svg') 定义的规则):
    适用于除了 src/icons 目录之外的所有 .svg 文件。通过 .exclude.add(resolve('src/icons')) 操作,明确把 src/icons 目录下的 .svg 文件排除在这条规则的应用范围之外,意味着项目中其他位置的 .svg 文件会按照后续常规配置的加载方式(可能是转译为其他格式、进行常规的模块处理等,具体取决于整体项目中其他相关 Webpack 配置,这里未完整展示)来处理。
    src/icons 目录下 .svg 专属规则(rule('icons') 定义的规则):
    专门针对 src/icons 目录下的 .svg 文件生效。通过 .include.add(resolve('src/icons')) 精准指定只有该目录下的 .svg 文件才应用这条规则,并且后续配置了使用 svg-sprite-loader 来进行特定处理,与常规 .svg 文件处理区分开来。
    2. 处理方式不同
    常规 .svg 规则:
    代码中未详细展示其具体的处理动作,但可以推测是按照一般的模块处理逻辑,比如可能是将 .svg 文件当作普通的静态资源模块,在构建时根据项目配置进行诸如复制到输出目录、进行必要的路径调整等常规操作,使其能在项目中正确被引用(例如在 HTML 里通过正确的相对路径引用 .svg 文件等)。
    src/icons 目录下 .svg 专属规则:
    使用了 svg-sprite-loader 这个特定的 loader 来处理。这个 loader 的作用是将多个 .svg 文件合并成一个雪碧图(Sprite),把每个 .svg 文件里的图形内容转化为 <symbol> 元素,并根据配置的 symbolId 规则(这里是 'icon-[name]')为每个 <symbol> 元素生成唯一的 id。这样在 HTML 等页面中就可以通过引用这个雪碧图以及对应的 id 方便地复用各个 SVG 图标,避免了多次单独加载 .svg 文件,提高了页面加载性能以及图标管理和使用的便利性。

 */
3.组件SvgIcon封装
  • 在项目src/compoent目录下新增SvgIcon文件夹,里面定义一个index.vue
  • index.vue组件作为子组件,将来被其他组件引用,
  • 以下代码中有内部和外部两种图标方式
3.1 index.vue 
<template>
  <!-- 外部 -->
  <div
    v-if="isExternal"
    :style="styleExternalIcon"
    class="svg-external-icon svg-icon"
    :class="className"
  ></div>
  <!-- 内部 -->
  <svg v-else class="svg-icon" :class="className" aria-hidden="true">
    <use :xlink:href="iconName"></use>
  </svg>
</template>
<script setup>
import { defineProps, computed } from "vue";
import { isExternal as external } from "@/utils/validata.js";
// 创建为组件首先考虑到接收的参数
const props = defineProps({
  icon: {
    type: String,
    required: true,
  },
  className: {
    type: String,
    default: "",
  },
});
// 第二点考虑到是不是外部,还是内部,可以使用计算属性,computed.下面方法是判断外部的
const isExternal = computed(() => external(props.icon));

// 外部图标的话就添加一个样式
const styleExternalIcon = computed(() => ({
  mask: `url(${props.icon}) no-repeat 50% 50%`,
  "-webkit-mask": `url(${props.icon}) no-repeat 50% 50%`,
}));

console.log(isExternal.value, "isExternal");
// 内部图标

const iconName = computed(() => `#icon-${props.icon}`);
</script>
<style>
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}

.svg-external-icon {
  background-color: currentColor;
  mask-size: cover !important;
  display: inline-block;
}
</style>
 4.关于require.context方法
  • 核心就是使用了webpack内置的require.context方法
  • 详细参数解释点击这里官网传送门
  • 这里我的svg文件都放在了src/icons/svg目录下了(根据自己需求存放即可,不固定)在icons下再次创建index.js文件
/**
 * 1:导入所有的svg图标
 * 2:完成SvgIcon的全局注册
 * https://webpack.docschina.org/guides/dependency-management/#requirecontext
 * 通过 require.context() 函数来创建自己的 context
 */
import SvgIcon from '@/components/SvgIcon'
/**
 * 搜索./svg下面的文件 ,是否有子目录,所以false,匹配的文件
 */
const svgRequire = require.context('./svg', false, /\.svg$/)//方法来svg注册,接收三个参数1:搜索./svg下面的文件 ,2是否有子目录,所以false,3匹配的文件.svg结尾的文件
//此时返回了一个require函,可以接收一个request的参数,用于requer的导入
//该函数提供三个属性,可以通过svgRequire.keys()获得所有的svg图标
//便利图标,吧图标作为request参数传入到,svgRequire,导入函数种,完成本地svg图标的导入
console.log(svgRequire.keys(), 'svgRequire.keys()')
svgRequire.keys().forEach(svgIcon => svgRequire(svgIcon))
export default app => {
  //导出一个函数,这个函数接收app的一个参数,通过挨app函数的component方法完成注册,两个参数,一个名字,一个实例icon
  app.component('svg-icon', SvgIcon)
}
 5.全局注册
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia'
 
import SvgIcon from '@/components/SvgIcon/index.vue'//注册的组件
import installIcons from '@/icons'//所有的icon
const app = createApp(App)
app.component('svg-icon', SvgIcon)
app.use(createPinia())
app.use(router)
app.use(installIcons)
app.mount('#app')
6.组件使用
 <svg-icon icon="user"></svg-icon>

 7.使用效果

 

 8.目录结构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2272626.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

谷歌SEO真的需要很长时间吗?

关键在于策略与执行力&#xff0c;很多人在刚开始做谷歌SEO时&#xff0c;都会产生一种挫败感&#xff0c;觉得排名变化太慢&#xff0c;看不到显著效果。这其实是因为SEO本身是一项需要时间的工作&#xff0c;特别是在竞争激烈的领域。但如果策略得当、执行力强&#xff0c;时…

耐高压26V输入5V升压充电8.4V芯片

HU6877作为一款集成了26V高耐压保护的5V升压至8.4V两节锂电池充电管理IC&#xff0c;凭借其高效升压、智能充电管理、多重安全保护及高耐压特性&#xff0c;在高端手电筒、便携式医疗设备、无人机等领域展现出了广泛的应用前景。本文将详细探讨HU6877的技术特点、工作原理、应用…

linuxCNC(六)配置LinuxCNC完成伺服控制

这里写目录标题 1、 cia402安装2、找伺服描述文件&#xff08;xml&#xff09;3、配置ethercat-config.xml3.1、打开hal-cia402/example/ethercat-conf.xml3.2、修改 ethercat-conf.xml文件中vid"0x000116c7" pid"0x003e0402"3.3、其他参数&#xff0c;根据…

【数据结构】链表(2):双向链表和双向循环链表

双向链表&#xff08;Doubly Linked List&#xff09; 定义&#xff1a; 每个节点包含三个部分&#xff1a; 数据域。前驱指针域&#xff08;指向前一个节点&#xff09;。后继指针域&#xff08;指向下一个节点&#xff09;。 支持从任意节点向前或向后遍历。 #define dat…

指针 const 的组合

1、首先来了解一下常量 const int num 5&#xff1b; 那么num的值是5&#xff0c; num的值不可修改 2、来了解一下指针 int value 5; int* p &value; 我喜欢吧指针和类型放一起&#xff0c;来强调p是一个指针类型&#xff0c; 而赋值的时候就得赋值一个int类型的地址…

Tableau数据可视化与仪表盘搭建-数据可视化原理

目录 内容 做个小实验 数据如何变成图表 1 2 维度和度量定义 3 度量映射图形&#xff0c;维度负责区分 1 可映射的数据类型 2 可视化字典 3 使用Tableau将数据变成图表(Tableau可视化原理) 1 2 拖拽 3 具体操作 4 总结 内容 点击左下角的工作表 tableau可以自动…

【WRF数据准备】气象驱动数据-ERA5是否需要单层位势数据?

目录 气象驱动数据-ERA5是否需要单层位势(Geopotential)数据?位势(Geopotential)输入的重要性Vtable的管理参考气象驱动数据-ERA5是否需要单层位势(Geopotential)数据? 本博客参考WRF论坛中讨论内容-How to use ERA5 Data From Copernicus Database,总结位势(Geopot…

用ResNet50+Qwen2-VL-2B-Instruct+LoRA模仿Diffusion-VLA的论文思路,在3090显卡上训练和测试成功

想一步步的实现Diffusion VLA论文的思路&#xff0c;不过论文的图像的输入用DINOv2进行特征提取的&#xff0c;我先把这个部分换成ResNet50。 老铁们&#xff0c;直接上代码&#xff1a; from PIL import Image import torch import torchvision.models as models from torch…

常见中间件漏洞(tomcat,weblogic,jboss,apache)

先准备好今天要使用的木马文件 使用哥斯拉生成木马 压缩成zip文件 改名为war后缀 一&#xff1a;Tomcat 1.1CVE-2017-12615 环境搭建 cd vulhub-master/tomcat/CVE-2017-12615 docker-compose up -d 1.首页抓包&#xff0c;修改为 PUT 方式提交 发送shell.jsp 和木马内容 …

嵌入式科普(26)为什么heap通常8字节对齐

目录 一、概述 二、newlibc heap 2.1 stm32cubeide .ld heap 2.2 e2studio .ld heap 三、glibc源码 3.1 Ubuntu c heap 四、总结 一、概述 结论&#xff1a;在嵌入式c语言中&#xff0c;heap通常8字节对齐 本文主要分析这个问题的分析过程 二、newlibc heap newlibc…

大数据-240 离线数仓 - 广告业务 测试 ADS层数据加载 DataX数据导出到 MySQL

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…

CTF杂项——[NSSRound#4 SWPU]Pixel_Signin

得到一个像素点 提取像素点 脚本 from PIL import Image result open(1.txt,w) img Image.open("Pixel_Signin.png") img img.convert(RGB) for i in range(31):for j in range(31):r,g,b img.getpixel((j,i))print(r,g,b,end ,fileresult) 运行之后得到 把它…

Harmony开发【笔记1】报错解决(字段名写错了。。)

在利用axios从网络接收请求时&#xff0c;发现返回obj的code为“-1”&#xff0c;非常不解&#xff0c;利用console.log测试&#xff0c;更加不解&#xff0c;可知抛出错误是 “ E 其他错误: userName required”。但是我在测试时&#xff0c;它并没有体现为空&#xff0c;…

springCloudGateWay使用总结

1、什么是网关 功能: ①身份认证、权限验证 ②服务器路由、负载均衡 ③请求限流 2、gateway搭建 2.1、创建一个空项目 2.2、引入依赖 2.3、加配置 3、断言工厂 4、过滤工厂 5、全局过滤器 6、跨域问题

韩国机场WebGIS可视化集合Google遥感影像分析

目录 前言 一、相关基础数据介绍 1、韩国的机场信息 2、空间数据准备 二、Leaflet叠加Google地图 1、叠加google地图 2、空间点的标记及展示 3、韩国机场空间分布 三、相关成果展示 1、务安国际机场 2、有同类问题的机场 四、总结 前言 12月29日8时57分左右务安国际机…

电子电气架构 --- 设计车载充电机的关键考虑因素

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

python进阶06:MySQL

课后大总结 Day1 一、数据库命令总结 1.连接数据库 连接数据库进入mysql安装目录打开bin文件夹&#xff0c;输入cmd(此命令后无分号)mysql.exe -u root -ppassword命令后输入密码:root 设置密码set passwordpassword("root123"); 查看所有数据库show databases; …

php反序列化原生态 ctfshow练习 字符串逃逸

web262 拿着题审计一下 <?php error_reporting(0); class message{public $from;public $msg;public $to;public $tokenuser;public function __construct($f,$m,$t){$this->from $f;$this->msg $m;$this->to $t;} }$f $_GET[f]; $m $_GET[m]; $t $_GET[t…

探秘前沿科技:RFID 与 NFC,开启智能识别新篇

RFID&#xff08;射频识别&#xff09;与NFC&#xff08;近场通信&#xff09;作为两种基于射频技术的无线通信方式&#xff0c;在现代社会中发挥着越来越重要的作用。尽管它们都具备非接触式识别和通信的能力&#xff0c;但在工作原理、应用场景、技术细节等方面存在着显著的差…

【04】优雅草央千澈详解关于APP签名以及分发-上架完整流程-第四篇安卓APP上架之vivo商店-小米商店,oppo商店,应用宝

【04】优雅草央千澈详解关于APP签名以及分发-上架完整流程-第四篇安卓APP上架之vivo商店-小米商店&#xff0c;oppo商店&#xff0c;应用宝 背景介绍 接第三篇上架华为&#xff0c;由于华为商店较为细致&#xff0c;本篇幅介绍其他4类商店相对简要一点&#xff0c;剩下其他更…