原生JavaScript如何为两类行内编辑组件复用同一套操作函数
问题根源
你遇到的问题核心是HTML页面中重复使用了相同的id属性,id在全局必须唯一,document.getElementById()永远只会返回页面中第一个匹配的元素,所以不管你点击哪个组件,实际操作的都是顶部第一个组件的元素。
改造方案
第一步:修改HTML代码
- 把所有重复的id替换为class属性
- 调用事件函数时传入当前触发元素
this,用于定位所属组件
改造后HTML示例:
<h3>with icons</h3> <div class="c-inline-edit c-inline-edit--icons"> <div class="c-inline-edit-wrapper border-yes"> <input class="c-inline-edit-input c-readonly-input" type="text" value="Lorem ipsum" onclick="yesEdit(this)" readonly/> <a class="btn-edit" onclick="yesEdit(this)"><span class="icon icon-16-edit-default-mono"></span></a> </div> <div class="c-btn-set-icon"> <a class="btn-cancel c-btn c-btn-secondary" onclick="noEdit(this)"><span class="icon-16-close-mono"></span></a> <a class="btn-save c-btn c-btn-primary" onclick="noEdit(this)"><span class="icon-checkmark-mono"></a> </div> </div> <h3>with buttons</h3> <div class="c-inline-edit c-inline-edit--buttons"> <div class="c-inline-edit-wrapper border-yes"> <input class="c-inline-edit-input c-readonly-input" type="text" value="Lorem ipsum" onclick="yesEdit(this)" readonly/> <a class="btn-edit" onclick="yesEdit(this)"><span class="icon icon-16-edit-default-mono"></span></a> </div> <div class="c-btn-set"> <a class="btn-cancel c-btn c-btn--mini c-btn--info" onclick="noEdit(this)">Cancel</a> <a class="btn-save c-btn c-btn--mini c-btn--outline" onclick="noEdit(this)">Save</a> </div> </div>
第二步:修改JS代码
- 新增变量记录当前处于编辑状态的组件,处理键盘事件场景
- 改写函数逻辑,通过触发元素向上查找所属组件容器,仅在容器内操作对应元素,避免跨组件影响
改造后JS代码:
// 记录当前激活的编辑组件 let activeEditComponent = null; document.addEventListener('keydown', function(event){ if(!activeEditComponent) return if(event.key === "Escape" || event.key === "Enter") { noEdit(activeEditComponent); } }); function yesEdit(target) { // 定位当前触发元素所属的组件根容器 const component = target.closest('.c-inline-edit'); activeEditComponent = component; // 仅在当前组件内查找元素操作 component.querySelector('.btn-edit').style.display = "none"; component.querySelector('.btn-save').style.display = "inline-block"; component.querySelector('.btn-cancel').style.display = "inline-block"; const editWrapper = component.querySelector('.c-inline-edit-wrapper'); editWrapper.classList.replace("border-yes", "border-no"); const input = component.querySelector('.c-inline-edit-input'); input.removeAttribute("readonly"); input.classList.replace("c-readonly-input", "c-input"); input.focus(); } function noEdit(target) { // 兼容键盘事件和点击事件的入参差异 const component = target.classList.contains('c-inline-edit') ? target : target.closest('.c-inline-edit'); if(!component) return; activeEditComponent = null; component.querySelector('.btn-edit').style.display = "inline-block"; component.querySelector('.btn-save').style.display = "none"; component.querySelector('.btn-cancel').style.display = "none"; const editWrapper = component.querySelector('.c-inline-edit-wrapper'); editWrapper.classList.replace("border-no", "border-yes"); const input = component.querySelector('.c-inline-edit-input'); input.setAttribute("readonly", ""); input.classList.replace("c-input", "c-readonly-input"); }
内容的提问来源于stack exchange,提问作者iosSicilian
相关产品推荐
相关产品推荐

