封装svg图标组件

简介: 封装svg图标组件

前言🌴🌴


在项目开发的过程中,我们会使用到大量的SVG图标,那么如果我们在项目中直接进行引用这样就太不方便,今天就来讲一下如何封装一个支持本地 SVG 图标和在线 SVG 图标的组件 svg-icon


什么是SVG图标?🥝🥝


简介:SVG是一种可伸缩的矢量图型(就是用标签代码来画图),它基于XML并用于描述图形的语言;如果我们通过vscode打开SVG图片,会发现他是基于一大串代码实现的。这和其他图片是以像素来描绘的不一样。

  • 不同于用像素来描绘的矩阵图像(JPG、PNG、GIF),SVG是和分辨率无关,也就是说,他和其他图片不同的地方就在于他放大也不会失真,图片依旧保持清晰。;
  • SVG图像可以通过JS和DOM操作来创建和操控;
  • SVG有自己庞大的语法和较大的复杂度,我们这里只是了解下有这种图像格式;


在本地引入一些svg图标 🍂🍂


介绍一下require.context


在接下来的工作开始之前,首先要介绍一下要使用到的API:

require.context方法进行简介:

他其实是一个webpack的API,获取一个特定的上下文,主要用来实现自动化导入模块。

使用场景:如果遇到从一个文件夹引入很多模块的情况,可以使用这个API,它会遍历文件夹中的指定文件,然后自动导入,使得不需要每次显式的调用import导入模块

接收三个参数:require.context(directory,useSubdirectories,regExp)

  • directory这个参数表明要检索的目录
  • useSubdirectories传入一个布尔值,表明是否检索子文件
  • regExp匹配的正则表达式,一般是文件名

值得注意的是require.context函数执行后返回的是一个函数,并且这个函数有3个属性,我们重点了解其中的一个

  • keys {Function} -返回匹配成功模块的名字组成的数组


开始配置


首先在src下面创建icons文件夹,在src/icons里面创建svg文件夹,在svg文件夹中引入svg图片,

同时在svg文件夹的平级创建index.js文件

然后在index.js文件中进行一些配置:

  • 首先引入SvgIcon这个组件
  • 然后使用require.context函数,返回一个函数,定义为svgRequire
  • 然后通过遍历svgRequire.keys()来获取匹配的svg路径
  • 注意返回的svgRequire函数接收一个参数,用于指定要导入的文件路径。通过在循环中调用svgRequire(svgIcon),我们将每个图标文件路径作为参数传递给这个导入函数,以完成对每个图标文件的导入操作。
  • 具体来说,这些导入的图标文件将被 webpack 处理,并根据配置将它们打包到最终生成的 JavaScript bundle 中。
  • 当你在应用程序的其他组件中使用 <svg-icon> 组件时,实际上是在使用已导入到 JavaScript bundle 中的 SVG 图标模块。这些图标模块可以根据需要在运行时动态加载和渲染。
  • 因此我们还需要进行一些webpack的配置
import SvgIcon from '@/components/SvgIcon';
// 使用这个api来完成导入
// https://webpack.docschina.org/guides/dependency-management/#requirecontext
const svgRequire = require.context('./svg', false, /.svg$/);
svgRequire.keys().forEach((svgIcon) => {
  svgRequire(svgIcon);
});
// 完成全局注册,这里传入的是main.js中创建的app实例
export default (app) => {
  app.component('svg-icon', SvgIcon);
};


如何封装svg组件 🐤🐤


首先我们需要在scr/component下面创建一个SvgIcon文件夹,并在里面创建一个index.vue文件

接下来我们要在创建的文件中写入下面的代码。


定义props部分


首先定义props,这里面我选择的是Vue3的setup语法糖的书写形式,这个props接收两个参数,一个icon就是要接受的icon图标的名字,当然,这个图标名称还要后续的进一步加工,也就是说,iconName是真正的名称,之所以要这么做是因为等一会需要进行配置项处理。另一个className是传递过来的icon的类名。

const props = defineProps({
  icon: {
    type: String,
    required: true
  },
  // 图标类名
  className: {
    type: String,
    default: ''
  }
});
// 项目内部图标,就相当于是一个名称
const iconName = computed(() => `#icon-${props.icon}`);

因为我们这个组件不仅要实现能够内部引用SVG图标还要能够引用外部的SVG图标(比如阿里的图标库),所以我们要进行一个判断该图标是否为外部引用的。

const isExternal = computed(() => external(props.icon));
-------------------------------
// 判断是否是外部图标
export function isExternal(path) {
  // 判断是否是这几个开头,如果是的话那么就是外部图标
  return /^(https?:|http)/.test(path);
}

这里面我进行了一个简单的判断,如果是以http或者https开头的,那么就认为这个SVG图标是从网站引用的,是一个在线的SVG图标。


HTML部分


下面这部分是进行简单的HTML处理,如果是外链的SVG图标就显示第一个,如果是项目内部的图标那就显示下面的

<template>
  <!-- 判断是否为外部图标 -->
  <div
    v-if="isExternal"
    :style="styleIsExternalIcon"
    class="svg-icon svg-external-icon"
    :class="className"
  ></div>
  <!-- 内部图标 -->
  <svg v-else class="svg-icon" :class="className" aria-hidden="true">
    <use :xlink:href="iconName"></use>
  </svg>
</template>

在这里使用了HTML中的svg标签,首先我们要先介绍一下svg标签:

  • SVG 代码以<svg> 元素开始,包括开启标签 <svg> 和关闭标签 </svg>
  • width 和 height 属性可设置此 SVG 文档的宽度和高度
  • version 属性可定义所使用的 SVG 版本,xmlns 属性可定义 SVG 命名空间。

那么这里的use又是什么呢?

  • 标记的作用是能从SVG文档内部取出一个节点,克隆它,并把它输出到别处。跟‘引用’很相似,但它是深度克隆
  • 比如你在同一个svg中定义了一个矩形元素:
<rect id="myRect" width="100" height="50" />

然后你想要在进行复用,那么你就可以使用use标签:

<use xlink:href="#myRect" />

这里面的xlink:href属性后面引用的图形元素的唯一标识符(通常是该元素的id属性的值)


简单的样式处理


// 外部图标的样式
const styleIsExternalIcon = computed(() => ({
  mask: `url(${props.icon}) no-repeat 50% 50%`,
  '-webkit-mask': `url(${props.icon}) no-repeat 50% 50%`
}));


引入插件并进行配置项处理🚴‍♀🚴‍♀


在进行完上面的处理之后,我们发现还是无法正常的显示svg图标,这是为什么呢?

我们还需要安装一个插件

npm i --save svg-sprite-loader
  1. SVG雪碧图生成:它将多个独立的SVG文件合并为一个SVG雪碧图,即将每个SVG图标放在一个共享的SVG容器中,从而减少HTTP请求的数量。这种合并使得加载和渲染多个SVG图标变得更加高效。
  2. 自动生成模块:插件会为每个SVG图标生成一个模块,并导出一个包含图标的使用代码。这样,可以像导入其他模块一样导入这些SVG图标模块,并直接在应用中使用它们。这简化了SVG图标的使用和管理。
  3. 图标的使用:在应用程序中,您可以通过使用导入的SVG图标模块的默认导出来使用图标。这样,您可以直接在HTML、CSS或JavaScript中引用图标,而无需将每个图标作为单独的文件引入

可以打开官网进行参考

VueCli官网的配置

module.exports = defineConfig({
chainWebpack(config) {
    config.module
      // 规则
      .rule('svg')
      .exclude.add(resolve('src/icons')).end();
    config.module
      // 规则
      .rule('icons')
      // 正则,解析 .svg格式文件
      .test(/.svg$/)
      // 解析的文件
      .include.add(resolve('src/icons')).end()
      // 新增了一个解析的loader
      .use('svg-sprite-loader')
      //具体的loader
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })
      .end();
  }
})

注意这个options中的symbolId,这一部分就是我们对svg图标的名称定义,这也是svg-sprite-loader这个插件所需要的,使用"icon-[name]",其中的name就是具体的svg图标名称。

我们在vue.config中进行配置,通过使用webpack中的exclude和include来指定要处理的路径,同时我们添加了一些处理规则,使用了正则表达式来解析指定的文件。


进行使用


<span class="svg-container">
    <svg-icon icon="user" />
</span>

image.png这样就完成了本地svg图片的导入


总结😄😄


这次学习了如何对项目中的SVG图标进行一个组件封装,掌握了许多之前没有学习到的知识,感觉收获满满

相关文章
|
JavaScript 定位技术
原生 js 实现类 3d 地图大屏展示自动高亮轮播、显示悬浮提示 tootip 的方案:svg + popper.js 定位引擎
原生 js 实现类 3d 地图大屏展示自动高亮轮播、显示悬浮提示 tootip 的方案:svg + popper.js 定位引擎
261 0
原生 js 实现类 3d 地图大屏展示自动高亮轮播、显示悬浮提示 tootip 的方案:svg + popper.js 定位引擎
|
5天前
|
JavaScript 定位技术 API
OpenLayers入门-第二篇、在vue3中使用elementplus制作图层控件,图层切换,显示隐藏,图层排序
OpenLayers入门-第二篇、在vue3中使用elementplus制作图层控件,图层切换,显示隐藏,图层排序
|
6天前
|
JavaScript 前端开发 API
【每周一个小技巧】如何自定义客服、生活号组件的样式
【每周一个小技巧】如何自定义客服、生活号组件的样式
31 7
|
6天前
【sgDragSize】自定义组件:自定义拖拽修改DIV尺寸组件,适用于窗体大小调整
【sgDragSize】自定义组件:自定义拖拽修改DIV尺寸组件,适用于窗体大小调整
|
6天前
elementUI引用el-image-viewer组件全局方法预览大图
elementUI引用el-image-viewer组件全局方法预览大图
|
6月前
|
前端开发
代码方式引入iconfont图标
代码方式引入iconfont图标
91 0
|
11月前
|
数据可视化 JavaScript 前端开发
ElementUI实现表格内嵌进度条功能
ElementUI实现表格内嵌进度条功能
412 1
|
12月前
|
前端开发 JavaScript API
Concis组件库封装——Popover气泡卡片
Concis组件库封装——Popover气泡卡片组件记录
116 1
|
JavaScript
Vue实现图片大图预览,v-viewer组件的使用方法演示
Vue实现图片大图预览,v-viewer组件的使用方法演示
310 0
antd组件库封装74-subMenu下拉菜单编码-完美组件2
antd组件库封装74-subMenu下拉菜单编码-完美组件2
63 0
antd组件库封装74-subMenu下拉菜单编码-完美组件2