Angular 6中点击按钮为SVG路径添加类失效问题排查
Angular 6中SVG路径元素添加类失效问题排查
咱们来拆解一下你遇到的问题——为什么同样的逻辑在ngOnInit里能跑通,放到按钮点击事件里就不行了。
核心问题:SVG的load事件只触发一次
当你在ngOnInit里给<object>标签添加load监听时,这时候SVG大概率还处于加载过程中,所以等它加载完成时,load事件会被正常触发,回调里的代码就能顺利执行。但等到你点击按钮的时候,SVG早就加载完成了,load事件已经触发过一次,不会再响应新添加的监听,所以回调里添加类的代码根本不会执行。你能看到按钮点击弹出alert,说明click函数本身是正常执行的,问题就出在load事件的时机上。
ngOnInit和按钮点击事件的关键差异
ngOnInit的执行时机:这是Angular组件初始化的生命周期钩子,在组件第一次渲染完成后立即执行。此时页面DOM元素已经存在,但外部资源(比如你通过<object>引入的SVG)可能还在加载,所以这时候添加load监听刚好能捕获到SVG加载完成的节点。- 按钮点击事件的执行时机:这是用户交互触发的事件,距离组件初始化已经过去了一段时间,SVG早已经加载完毕,
load事件已经触发过,自然不会再响应后续添加的监听。
解决方案
这里提供两种简单可行的处理方式:
1. 提前缓存SVG文档对象
在ngOnInit的load回调里,把加载完成的SVG文档对象保存到组件属性中,后续点击按钮时直接使用这个缓存的对象即可:
private svgDoc: Document | null = null; ngOnInit() { const svgObject = document.getElementById("biharsvg") as HTMLObjectElement; svgObject.addEventListener("load", () => { this.svgDoc = svgObject.contentDocument; // 这里可以执行初始化时的SVG操作 }); } click() { alert("hello"); if (this.svgDoc) { const wchamparan = this.svgDoc.getElementById("wchamparan"); wchamparan?.classList.add("mystyle"); console.log("hello"); } }
2. 判断SVG加载状态,直接执行操作
在点击事件里先检查SVG是否已经加载完成,如果已经加载就直接操作,极端情况下(比如用户点击按钮时SVG还没加载完)再监听load事件:
click() { alert("hello"); const svgObject = document.getElementById("biharsvg") as HTMLObjectElement; if (svgObject.contentDocument) { // SVG已加载完成,直接操作DOM const wchamparan = svgObject.contentDocument.getElementById("wchamparan"); wchamparan?.classList.add("mystyle"); console.log("hello"); } else { // 极端情况:SVG仍在加载中,监听load事件 svgObject.addEventListener("load", () => { const wchamparan = svgObject.contentDocument?.getElementById("wchamparan"); wchamparan?.classList.add("mystyle"); console.log("hello"); }); } }
内容的提问来源于stack exchange,提问作者user7341673
相关产品推荐
相关产品推荐

