如何为ArcGIS API for JS弹窗内容中的按钮绑定addEventListener事件
问题背景
使用ArcGIS JS API 4.x的popupTemplate方法创建自定义弹窗时,通过HTML在弹窗内容中添加按钮后,无法为按钮绑定addEventListener事件监听器,获取按钮元素时控制台返回null。
复现代码逻辑如下:
- 返回HTML在弹窗内容中创建按钮
const popupTemplate = { // autocasts as new PopupTemplate() title: "Population in {NAME}", content: populationChange, }; layer.popupTemplate = popupTemplate; function populationChange(feature) { const div = document.createElement("div"); div.innerHTML = "<input type='button' id='btn' value='CLICK'>"; return div; }
- 监听popup的content属性变化
view.popup.watch("content", (newValue, oldValue, propertyName, target) => {......});
- 通过
querySelector("#btn")获取按钮后绑定事件,执行失败,控制台打印btn结果为null,对应代码:
const btn = document.querySelector("#btn"); console.log(btn) btn.addEventListener( "click", function () { lert("HELLO WORLD!"); }, false );
控制台输出效果:
故障原因
事件绑定时机错误:view.popup.watch("content")触发时,弹窗的DOM节点还未完成渲染挂载到页面,此时调用document.querySelector查找弹窗内的按钮,必然返回null。另外代码中点击回调内写的是lert,遗漏了开头的a,即便成功获取到元素也会触发函数未定义报错。
解决方法
方案1:创建DOM元素时直接绑定事件(推荐)
既然弹窗内容是通过document.createElement动态生成的,不需要等DOM渲染后再查找元素,在创建按钮节点时直接绑定事件即可,完全规避DOM查找时机问题,修改代码如下:
function populationChange(feature) { const div = document.createElement("div"); // 单独创建按钮元素,不直接拼接innerHTML字符串 const btn = document.createElement("input"); btn.type = "button"; btn.id = "btn"; btn.value = "CLICK"; // 创建节点时直接绑定点击事件 btn.addEventListener("click", () => { alert("HELLO WORLD!"); }, false); div.appendChild(btn); return div; }
该方法稳定性最高,不依赖弹窗组件的渲染生命周期,不会出现元素查找失败的问题。
方案2:等待DOM渲染完成后再查找绑定
如果需要在DOM渲染完成后再做事件绑定,不要监听content属性,改为监听弹窗的selectedFeature属性,等待下一帧DOM挂载完成后再查找元素:
view.popup.watch("selectedFeature", (currentFeature) => { if (!currentFeature) return; // 等待DOM渲染挂载完成后再查询元素 setTimeout(() => { const btn = document.querySelector("#btn"); if (btn) { btn.addEventListener("click", () => { alert("HELLO WORLD!"); }, false); } }, 0); });
注意:页面中id属性必须唯一,如果同时弹出多个要素的弹窗,会出现id重复冲突,建议替换为class选择器查找元素。
内容的提问来源于stack exchange,提问作者llllllllc
相关产品推荐
相关产品推荐

