前言
在前端项目中,使用自定义的icon图标时,需要引用很长的相对地址,添加和修改图标会变得很麻烦。
imgsrc="./long/path/to/your/svg/icon.svg"/
有没有更简单的icon图标引入方式呢?像使用组件库中的ICON组件一样。
a-icontype="fast-backward"/
答案是肯定的,我们可以通过SVGSprite简化自定义图标的使用方式。
SVGSprite
如果你没听过SVGSprite,也许听过雪碧图(CSSSprite),如下图所示。雪碧图是为了减少网络请求次数,将许多小图标整合到一张图片上,然后通过CSS定位技术显示特定位置的图标。雪碧图在使用上存在一些弊端,目前已经很少使用了。
类似的SVGSprite是通过symbol和use实现的。symbol元素可以把svg图标定义成一个图形模板对象,use元素通过xlink:href属性引用symbolid展示图形。下面代码定义了三个symbol图形模板,此时图形并不会展示到页面上,通过use元素引用symbolid后才可展示图形。
//定义图形svgwidth="0"height="0"symbolid="shape1"circlecx="40"cy="40"r="24"style="stroke:#;fill:#00cc00"//symbolsymbolid="shape2"rectx="10"y="10"height=""width=""style="stroke:#;fill:#00cc00"//symbolsymbolid="shape3"polygonpoints="10,,,50"style="stroke:#;fill:#cc;"//symbol/svg//引用图形svgwidth=""height=""usexlink:href="#shape1"x="0"y="25"/usexlink:href="#shape1"x="60"y="25"/usexlink:href="#shape2"x=""y="0"/usexlink:href="#shape3"x=""y="10"//svg
通过上面示例代码可以看出:
use元素可以跨svg元素引用symbol。
use可以重复引用symbol。
如果将项目中的svg图标用symbol元素定义成图形模板,并将其组合成一个大的svg加载到页面中,如下图所示。那么我们可以在页面的任何位置,只需要一行代码就可以引用这个图标了。
svgclass="size"usexlink:href="#icon-tubiao"//svg
进一步,将use对symbol元素的引用封装到组件中,通过动态的传递svg文件名来展示不同的svg图标,从而实现简洁的引用自定义图标。
svg-iconname="tubiao"/
如何将svg图标组合一起呢?svg-sprite-loader可以帮我们实现。
svg-sprite-loader使用svg-sprite-loader会把项目中引入的svg图标塞到一个个symbol中,合成一个大的svg,最后将这个大的svg插入到body元素中。
下面基于vue2.0介绍svg-sprite-loader配置。
01
安装svg-sprite-loader
npmisvg-sprite-loader-D
02
配置vue.config.js
本示例中是将项目中的svg图标统一放到在src/icons/svg目录中,可根据实际需要调整。配置svg-sprite-loader前,首先清除webpack默认loader(如url-loader,file-loader等)对src/icons/svg目录中svg图标处理,然后添加svg-sprite-loader对src/icons/svg目录下的svg图标的处理。指定symbolId为文件名加上“icon-”前缀。
constpath=require("path");functionresolve(dir){//__dirname项目根目录的绝对路径returnpath.join(__dirname,dir);}module.exports={chainWebpack:(config)={//默认规则不处理src/icons目录下的svg文件config.module.rule("svg").exclude.add(resolve("src/icons/svg")).end();//针对icons/svg目录下的文件添加svg-sprite-loader规则config.module.rule("svgicon").test(/\.svg/).include.add(resolve("src/icons/svg")).end().use("svg-sprite-loader").loader("svg-sprite-loader").options({symbolId:"icon-[name]",});},}
03
封装SvgIcon组件
将use对symbol元素的引用封装到组件中,通过动态的传递svg文件名来展示不同的svg图标。
templatesvg:class="svgClass"aria-hidden="true"use:xlink:href="iconName"//svg/templatescriptexportdefault{name:"SvgIcon",props:{name:{type:String,required:true,},className:{type:String,},},