vue动态渲染svg,添加点击事件
欢迎来到【前端小鱼的github】,阅读更多原创技术文章业务需求(在vue项目中)1.在页面显示svg内容2.监听svg内部的点击事件3.动态改变svg内部元素的属性和值。经过多次实验,用embed、img等标签改变src属性并不能实现以上所有功能(尤其是svg内部的点击事件),最终使用Vue.extend()方法完全实现,代码也比较简洁.html结构如下:
将svg文件的内容直接复制粘贴到.vue文件中,直接在标签中添加@click事件即可完成需求。方法很简单,但是会导致文件过长。实现思路本文不再赘述1.创建一个xhr对象constxhr=newXMLHttpRequest();this.svgUrl=。..;//svg的绝对地址,浏览器打开就可以看到了xhr.open("GET",this.svgUrl,true);xhr.发送();2.监听xhr对象(获取svg的dom->添加事件->修改dom->转换为虚拟dom并挂载)xhr.addEventListener("load",()=>{//①获取svg的domconstresXML=xhr.responseXML;this.svgDom=resXML.documentElement.cloneNode(true);//console.log(this.svgDom);//②添加点击事件letbtn=this.svgDom.getElementById("...");btn.setAttribute("v-on:click","this.handleClick()");//↑↑↑这里注意:此时native事件handleClick在window层,见下面解决方案//③修改domthis.svgDom.getElementById("...").childNodes[0].nodeValue=...this.svgDom.getElementById("...").setAttribute("style",`....;fill:${this.photoResult.resultColor};...`);//↑↑↑使用js操作dom语法,动态设置svg组件的属性和值//④将svgDom对象转化为vue虚拟dom,创建实例挂起varoSerializer=newXMLSerializer();varsXML=oSerializer.serializeToString(this.svgDom);varProfile=Vue.extend({template:"
"+sXML+" "});新配置文件().$mount("#svgTemplate");});3.将methods中要执行的事件绑定到window上,供外部(刚刚添加的handleClick事件)调用asyncmounted(){window["handleClick"]=()=>{this.takePhoto();};},methods:{takePhoto(){...}}至此,需求基本完成:svg的动态渲染,使用js操作dom语法修改svg组件的属性和值,给svg组件动态添加事件handleClick,最后将takePhoto()事件绑定到window对象的handleClick上,这样你就可以放心大胆的在takePhoto()内容中写上你要执行的内容了!给svgdom组件添加事件时要特别注意:1、多次尝试后,只有setAttribute+v-on:click有效2、setAttribute不支持@click(非原生事件),会报语法错误3.addEventListener和onclickall将svgDom对象转换为vue的虚拟dom时会被vue拦截:1.如果报错如下,将importVuefrom"vue"改为importVuefrom"vue/dist/vue.esm.js"等解决方案本文不讨论,大家可以自行百度2.vue.extend()方法是vue的构造函数,用于动态创建vue实例。模板组件template只能有一个根元素3.$mount手动挂载到id为svgTemplate的元素上,挂载后会替换原来的dom(替换原来的