当前位置: 首页 > Web前端 > vue.js

vite+vue3下如何使用动态导入的svg-sprite精灵图片

时间:2023-03-31 21:44:31 vue.js

几个月前刚接触vue3的时候研究过,一直忘记分享。原因我的vue项目一般使用动态导入的svg-sprite,也就是说:如果是sprite图片,使用标签复用;并且页面的svg应该按需动态加载。我觉得这个性能比较好,在vue2实现起来也比较简单,但是我在vue3+vite下一直没有找到合适的解决方案,只有sprite图片没有动态导入。所以我想自己做一个。思路是先做一个vite插件,作为loader加载.svg文件,读取svg文件的内容,类似于raw-loader。然后需要一个组件,动态加载svg文件,并将svg文件的内容拼接成Sprite图片。代码vite.config.ts是这样写的:import{defineConfig,Plugin}from'vite'importvuefrom'@vitejs/plugin-vue'importfsfrom"fs";import{dataToEsm}from"rollup-pluginutils";constrawSvgPlugin:Plugin={name:'raw-svg-file-loader',transform(svg:string,filepath:string){//判断后缀是否为svgif(filepath.slice(-4)!=='.svg')返回空值;constcontent=fs.readFileSync(filepath).toString()return{//直接返回svg文件的原始内容code:dataToEsm(content)}},}exportdefaultdefineConfig({plugins:[vue(),rawSvgPlugin],})IconSvg.vue文件:从“vue”导入{defineComponent};constsvgParser=newDOMParser();导出默认defineComponent({name:“IconSvg”,props:{name:{type:String,default:''}},data(){return{getName:''}},watch:{//监听名称变化'$props.name':{//第一次执行immediate:true,asynchandler(){//拼接svg文件名constgetId=`icon-${this.name}`constname=`#${getId}`//动态加载constres=awaitimport(`../svg/${this.name}.svg`);//Sprite图像的DOM容器letcontainer=document.querySelector('#_SVG_SPRITE_CONTAINER_');if(!container||!container.querySelector(name)){if(!container){//如果容器还没有创建,创建一个(这里也可以直接写在index.html中)container=document.createElement('div');container.id='_SVG_SPRITE_CONTAINER_'container.setAttribute('xmlns','http://www.w3.org/2000/svg')container.setAttribute('style','position:absolute;width:0;height:0;溢出:隐藏')document.body.insertBefore(container,document.body.children[0]);}if(!container.querySelector(name)){//如果容器中没有这个svg,解析并制作svg的sprite图片constsvgElement=svgParser.parseFromString(res.default,"image/svg+xml").querySelector('svg');if(svgElement){//移除影响样式的属性for(constkeyof['width','height','x','y']){svgElement.removeAttribute(key)}svgElement.id=getId//插入容器container.appendChild(svgElementasSVGSVGElement)}}}this.getName=name;}}},})在main.ts中,只需要全局注册IconSvg组件即可:import{createApp}from'vue'importAppfrom'./App.vue'vue";createApp(App).component('svg-icon',IconSvg).mount('#app')是这样使用的:综上,这样做问题就解决了。可以动态导入svg生成sprite图片,但是方法有点不优雅,感觉有点投机取巧。本文转载自个人博客:vite+vue3下如何使用动态导入svg-sprite的博客(halberd.cn)