原生JS实现HTML按钮文本类数据属性切换且保留嵌套SVG图标
问题解决:切换按钮时保留SVG图标同时正常切换文本
问题场景
两个导航按钮:一个是带文本的菜单按钮(可切换"Menu"/"Close"),另一个是仅包含SVG图标的用户菜单按钮。当前点击按钮时,SVG图标会被移除,文本按钮功能正常,需要修改代码确保SVG完整,文本切换不受影响。
问题根源
- 事件目标错误:点击SVG时,
e.target指向的是SVG元素而非按钮本身,导致后续操作错误作用在SVG上。 - 无差别文本替换:代码对所有按钮执行
innerText替换逻辑,SVG按钮没有文本切换的data-text-swap属性,但仍被修改,直接清空了SVG内容。
修改方案
核心修改点
- 用
e.currentTarget替代e.target,确保始终操作绑定事件的按钮元素,而非内部的SVG。 - 给文本切换逻辑加判断:仅对带有
data-text-swap属性的按钮执行文本替换,SVG按钮跳过这部分。 - 清理其他激活按钮时,同样区分处理:带文本属性的按钮恢复文本,其他仅重置类和
aria-expanded属性。
修改后的JS代码
window.addEventListener("DOMContentLoaded", function() { const navigation = (() => { const buttons = document.querySelectorAll("[data-nav-toggle]"); const containers = document.querySelectorAll("[data-nav-container]"); if (!buttons.length) return; function menuToggleHandler() { buttons.forEach((button) => { button.addEventListener("click", toggleContainer); }); } function toggleContainer(e) { e.stopPropagation(); // 用currentTarget确保操作的是绑定事件的按钮,而非内部SVG toggleButtonAttributes(e.currentTarget); toggleContainers(e.currentTarget); } function toggleButtonAttributes(button) { button.classList.toggle("is-active"); const expandedValue = button.getAttribute("aria-expanded"); const setValue = expandedValue === "true" ? "false" : "true"; button.setAttribute("aria-expanded", setValue); // 仅对有data-text-swap的按钮执行文本切换 const hasTextSwap = button.hasAttribute("data-text-swap"); if (hasTextSwap) { const originalValue = button.getAttribute("data-text-original"); const swapValue = button.getAttribute("data-text-swap"); if (swapValue.trim() === button.innerText.trim()) { button.innerText = originalValue; } else { button.setAttribute("data-text-original", button.innerText.trim()); button.innerText = swapValue; } } // 清理其他激活的按钮 document.querySelectorAll(".is-active").forEach(function(buttonActive) { if (buttonActive !== button) { buttonActive.classList.remove("is-active"); buttonActive.setAttribute("aria-expanded", "false"); // 仅对有文本切换属性的按钮恢复文本 if (buttonActive.hasAttribute("data-text-swap")) { const originalText = buttonActive.getAttribute("data-text-original"); buttonActive.innerText = originalText; } } }); } function toggleContainers(button) { const parent = button .closest("nav") .querySelector("[data-nav-container]"); parent.classList.toggle("is-expanded"); document .querySelectorAll(".is-expanded") .forEach(function(parentExpanded) { if (parentExpanded !== parent) { parentExpanded.classList.remove("is-expanded"); } }); } menuToggleHandler(); })(); });
其他代码保持不变
- CSS代码无需修改:
button>svg { pointer-events: none; }
- HTML代码保持原结构即可,SVG按钮无需添加文本相关的data属性。
内容的提问来源于stack exchange,提问作者Mike Hermary
相关产品推荐
相关产品推荐

