如何将leaveDetails动态传递给事件处理器,避免重复绑定事件
问题描述
我希望将传入setLeaveDetails函数的leaveDetails传递给事件处理器,无需在setLeaveDetails函数中反复为leaveAccept和leaveDecline按钮添加或移除事件。请问能否使用currentLeaveDetails这类全局变量来实现,或者有其他可行方案?
HTML代码
<div id="leaveDetailsBox"> <div class="smallHeading" id="leaverSeekerHeading"> leave request details </div> <div class="leaveRequestInformation"> <div class="SingleInfo"> <p class="infoTitle">leave seeker name</p> <p class="infoDescription" id="leaveSeekerName"></p> </div> <div class="SingleInfo"> <p class="infoTitle">no. of days</p> <p class="infoDescription" id="noOfDaysOfLeave"></p> </div> <div class="SingleInfo"> <p class="infoTitle">status</p> <p class="infoDescription" id="leaveStatus"> pending </p> </div> <div class="SingleInfo"> <p class="infoTitle">reason</p> <p class="infoDescription" id="leaveReason"> Amritpal Singh sidhu </p> </div> <div class="SingleInfo d-none"> <p class="infoTitle">leave Decline reason</p> <p class="infoDescription" id="leaveDeclineReason"></p> </div> <div class="action" id="leaveRequestAction"> <button id="acceptBtn">approve</button> <button id="declineBtn">Decline</button> </div> </div> </div>
JavaScript代码
let leaveAcceptBtn = document.querySelector("#acceptBtn"); let leaveDeclineBtn = document.querySelector("#declineBtn"); function setLeavesDetails(leaveDetails) { leaverSeekerHeading.textContent = `${leaveDetails.leaveSeekerName}'s leave request details...`; leaveSeekerName.textContent = leaveDetails.leaveSeekerName; leaveReason.textContent = leaveDetails.leaveReason; leaveStatus.textContent = leaveDetails.status; leaveReason.textContent = leaveDetails.reason; if (leaveDetails.status !== "pending") { leaveRequestAction.classList.add("hide"); } else { leaveRequestAction.classList.remove("hide"); } } let declineHandler = (leaveDetails) => { Swal.fire({ title: "Are you sure to decline leave?", icon: "question", input: "text", inputPlaceholder: "Enter leave reason(If Any)", showCancelButton: true, showCloseButton: true, showConfirmButton: true, confirmButtonText: "Decline", confirmButtonColor: "#eb5353", cancelButtonText: "Cancel", customClass: { title: "custom-title", icon: "custom-icon", confirmButton: "custom-confirm-button", cancelButton: "custom-cancel-button", }, }).then((response) => { if (response.isConfirmed) { console.log(response.value); if (response.value.trim().length != 0 && response.value != " ") { updateLeaveStatus(leaveDetails._id, "declined", response.value); } else { updateLeaveStatus(leaveDetails._id, "declined"); } } }); }; let acceptHandler = (leaveDetails) => { console.log("accept leave btn clicked"); getLeaveSeekerEvents(leaveDetails); }; leaveAcceptBtn.addEventListener("click", acceptHandler); leaveDeclineBtn.addEventListener("click", declineHandler);
可行解决方案
方案1:使用全局变量
完全可以用全局变量实现,只需要在全局作用域声明一个变量,每次调用setLeavesDetails时更新它的值,事件处理器直接读取这个全局变量即可,不用反复绑定事件:
// 全局变量存储当前的leaveDetails let currentLeaveDetails = null; let leaveAcceptBtn = document.querySelector("#acceptBtn"); let leaveDeclineBtn = document.querySelector("#declineBtn"); function setLeavesDetails(leaveDetails) { // 更新全局变量 currentLeaveDetails = leaveDetails; leaverSeekerHeading.textContent = `${leaveDetails.leaveSeekerName}'s leave request details...`; leaveSeekerName.textContent = leaveDetails.leaveSeekerName; leaveReason.textContent = leaveDetails.leaveReason; leaveStatus.textContent = leaveDetails.status; leaveReason.textContent = leaveDetails.reason; if (leaveDetails.status !== "pending") { leaveRequestAction.classList.add("hide"); } else { leaveRequestAction.classList.remove("hide"); } } // 修改事件处理器,直接使用全局变量 let declineHandler = () => { const leaveDetails = currentLeaveDetails; if (!leaveDetails) return; // 防止未初始化的情况 Swal.fire({ title: "Are you sure to decline leave?", icon: "question", input: "text", inputPlaceholder: "Enter leave reason(If Any)", showCancelButton: true, showCloseButton: true, showConfirmButton: true, confirmButtonText: "Decline", confirmButtonColor: "#eb5353", cancelButtonText: "Cancel", customClass: { title: "custom-title", icon: "custom-icon", confirmButton: "custom-confirm-button", cancelButton: "custom-cancel-button", }, }).then((response) => { if (response.isConfirmed) { console.log(response.value); if (response.value.trim().length != 0 && response.value != " ") { updateLeaveStatus(leaveDetails._id, "declined", response.value); } else { updateLeaveStatus(leaveDetails._id, "declined"); } } }); }; let acceptHandler = () => { const leaveDetails = currentLeaveDetails; if (!leaveDetails) return; console.log("accept leave btn clicked"); getLeaveSeekerEvents(leaveDetails); }; // 只绑定一次事件 leaveAcceptBtn.addEventListener("click", acceptHandler); leaveDeclineBtn.addEventListener("click", declineHandler);
方案2:使用元素的dataset属性
如果不想用全局变量,可以把leaveDetails的关键信息(比如_id)或者整个对象转成JSON字符串存在按钮或容器的dataset中,事件触发时再读取解析:
let leaveAcceptBtn = document.querySelector("#acceptBtn"); let leaveDeclineBtn = document.querySelector("#declineBtn"); const leaveDetailsBox = document.querySelector("#leaveDetailsBox"); function setLeavesDetails(leaveDetails) { // 将leaveDetails转成JSON存在容器的dataset里 leaveDetailsBox.dataset.leaveData = JSON.stringify(leaveDetails); leaverSeekerHeading.textContent = `${leaveDetails.leaveSeekerName}'s leave request details...`; leaveSeekerName.textContent = leaveDetails.leaveSeekerName; leaveReason.textContent = leaveDetails.leaveReason; leaveStatus.textContent = leaveDetails.status; leaveReason.textContent = leaveDetails.reason; if (leaveDetails.status !== "pending") { leaveRequestAction.classList.add("hide"); } else { leaveRequestAction.classList.remove("hide"); } } // 修改事件处理器,从dataset读取数据 let declineHandler = () => { const leaveDataStr = leaveDetailsBox.dataset.leaveData; if (!leaveDataStr) return; const leaveDetails = JSON.parse(leaveDataStr); Swal.fire({ title: "Are you sure to decline leave?", icon: "question", input: "text", inputPlaceholder: "Enter leave reason(If Any)", showCancelButton: true, showCloseButton: true, showConfirmButton: true, confirmButtonText: "Decline", confirmButtonColor: "#eb5353", cancelButtonText: "Cancel", customClass: { title: "custom-title", icon: "custom-icon", confirmButton: "custom-confirm-button", cancelButton: "custom-cancel-button", }, }).then((response) => { if (response.isConfirmed) { console.log(response.value); if (response.value.trim().length != 0 && response.value != " ") { updateLeaveStatus(leaveDetails._id, "declined", response.value); } else { updateLeaveStatus(leaveDetails._id, "declined"); } } }); }; let acceptHandler = () => { const leaveDataStr = leaveDetailsBox.dataset.leaveData; if (!leaveDataStr) return; const leaveDetails = JSON.parse(leaveDataStr); console.log("accept leave btn clicked"); getLeaveSeekerEvents(leaveDetails); }; // 只绑定一次事件 leaveAcceptBtn.addEventListener("click", acceptHandler); leaveDeclineBtn.addEventListener("click", declineHandler);
方案对比
- 全局变量方案:实现简单,代码改动少,但要注意全局作用域的污染问题,适合小型项目或组件内部使用。
- dataset方案:更符合模块化思想,避免全局变量,但需要处理JSON序列化和反序列化,适合需要保持作用域干净的场景。
内容的提问来源于stack exchange,提问作者Amrit Sidhu
相关产品推荐
相关产品推荐

