You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript箭头函数中如何选取当前点击元素的相邻DOM节点

问题说明

现有某设置菜单的JS与HTML实现,菜单展示URL列表,每条URL旁配有一个'x'删除按钮,为某RSS应用的二次开发版本,实际运行效果如下:

x foo.com
x bar.com/rss
x baz.com/feed

renderSettings() 函数负责将JSON数组中的数据注入到<template id="settings-feed-item">模板节点中,模板内容不会直接在页面预览中展示,该函数同时会为每个删除按钮绑定onclick事件。
当前需求:点击某条URL旁的删除按钮时,为同条目的URL节点应用指定CSS样式。
现存问题:无法正确选中点击按钮对应的URL节点,尝试使用this关键字、closest()方法均失败,控制台抛出TypeError: undefined is not an object错误。

现有代码

HTML

<section id="feedsection">
  <ul id="feeds">
    <template id="settings-feed-item">
      <li>
        <a id="remove">x&emsp;</a><span id="feedurl"></span><a></a>
      </li>
    </template>
  </ul>
</section>

JS

// 渲染设置菜单
function renderSettings() {
  keywords.value = state.keywords;
  newsFeeds.innerHTML = '';
  state.feeds.forEach(f => {
    const el = document.importNode(feedItem.content, true).querySelector('li');
    el.querySelector('span').innerText = simplifyLink(f.url);
    // ...
    // 绑定删除按钮点击事件
    el.querySelectorAll('a')[0].onclick = () => {
      // 此处需要选中点击按钮旁的URL节点
    };
    // ...
  });
}

错误原因

  • 事件绑定使用了箭头函数,箭头函数不绑定自身的this上下文,因此回调内无法通过this获取触发事件的按钮元素,这是this相关写法失效的核心原因。
  • 模板内重复使用id属性:id="remove"、id="feedurl"违反HTML规范,id要求全局唯一,列表循环渲染多份条目后会出现id重复,导致DOM选择器匹配异常。
  • 原代码片段未将导入模板生成的li元素插入到页面DOM树中,也可能导致DOM查找方法执行失败。

正确实现

  1. 首先修改模板,将重复id替换为class,避免全局id冲突:
<template id="settings-feed-item">
  <li>
    <a class="remove">x&emsp;</a><span class="feedurl"></span><a></a>
  </li>
</template>
  1. 修改JS逻辑,在循环渲染条目时提前缓存当前条目的相关元素,事件回调内直接操作缓存的节点即可,无需额外做DOM查找,同时补全节点插入逻辑:
function renderSettings() {
  keywords.value = state.keywords;
  newsFeeds.innerHTML = '';
  state.feeds.forEach(f => {
    const el = document.importNode(feedItem.content, true).querySelector('li');
    // 提前缓存当前条目的URL节点和删除按钮
    const feedUrlEl = el.querySelector('.feedurl');
    const removeBtn = el.querySelector('.remove');
    
    feedUrlEl.innerText = simplifyLink(f.url);
    
    removeBtn.onclick = function() {
      // 直接操作当前条目的URL节点,添加样式
      // 方式1:添加预定义的CSS类
      feedUrlEl.classList.add('deleted-item');
      // 方式2:直接修改内联样式
      // feedUrlEl.style.textDecoration = 'line-through';
      // feedUrlEl.style.opacity = '0.5';
    };

    // 其余原有业务逻辑
    // ...
    // 将生成的条目插入页面列表
    newsFeeds.appendChild(el);
  });
}

如果不想修改原有id、也不想更换函数写法,也可以通过事件对象获取触发元素,再匹配相邻节点:

el.querySelectorAll('a')[0].onclick = (e) => {
  const currentBtn = e.currentTarget;
  const feedUrlEl = currentBtn.nextElementSibling;
  // 操作feedUrlEl添加样式即可
}

但该写法强依赖DOM相邻结构,后续模板结构调整很容易失效,且重复id的问题依然存在,不推荐使用。

内容的提问来源于stack exchange,提问作者Evan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 17:30:46