使用 HTMLElement.click() 方法时防止 JavaScript 冒泡 DOM

Ant*_*oss 5 javascript

我知道这看起来很奇怪,但我有一种情况,当我们将鼠标悬停在目标上时,我需要模拟单击事件。

\n\n

我目前正在使用 JavaScript 的.click()方法 \xe2\x80\x93 https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click,但点击冒泡到liDOM 中并activateAnchor()同时触发功能。我尝试过使用stopPropagation,但这没有效果。

\n\n

我的问题是:这是否可能,或者我是否需要以不同的方式处理这个问题。

\n\n

我这里有一个例子 \xe2\x80\x93 https://jsfiddle.net/dryrobe/vsq7czmx/43/

\n\n
const output = document.querySelector(\'.output\');\nconst switcherList = document.querySelector(\'[data-custom-switcher]\');\nconst switcherListItems = Array.from(switcherList.getElementsByTagName(\'li\'));\nconst switcherListItemsAnchors = Array.from(switcherList.getElementsByTagName(\'a\'));\n\nswitcherListItemsAnchors.map(switcherListItemAnchor => switcherListItemAnchor.addEventListener(\'mouseenter\', simulateClick.bind(switcherListItemAnchor)));\nswitcherListItems.map(switcherListItem => switcherListItem.addEventListener(\'click\', activateAnchor.bind(switcherListItem)));\n\n// This should only fire when each item is clicked, but it fires on hover.\nfunction activateAnchor() {\n  event.stopPropagation();\n  addMessage(\'activateAnchor\');\n}\n\n// This should fire when each item is hovered\nfunction simulateClick() {\n  event.stopPropagation();\n  this.click();\n  addMessage(\'simulateClick\');\n}\n\nfunction addMessage(message) {\n  if(message === \'activateAnchor\') {\n    output.innerHTML += `<h1>This is the activateAnchor function</h1>`;\n  }\n  if(message === \'simulateClick\') {\n    output.innerHTML += `<h1>This is the simulateClick function</h1>`;\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Cer*_*nce 4

.click()将导致传播点击事件。如果您希望点击事件不传播,则必须添加点击侦听器并调用stopPropagation该事件。您无法阻止click事件从mouseenter处理程序内部传播。检查e.isTrusted事件是由 Javascript 触发还是由用户实际点击触发 - 如果为 false,则由 Javascript 触发,您可以调用stopPropagation

switcherListItemsAnchors.forEach((switcherListItemAnchor) => {
  switcherListItemAnchor.addEventListener('mouseenter', simulateClick.bind(switcherListItemAnchor))
  switcherListItemAnchor.addEventListener('click', (e) => {
    if (!e.isTrusted) {
      e.stopPropagation();
    }
  })
});
Run Code Online (Sandbox Code Playgroud)

另请注意,您只能用于.map从另一个数组创建一个数组。对于副作用(例如添加侦听器),请forEach改用。

.bind如果this绑定函数内部已打算成为单击的元素(或者如果this未在函数内部使用),则也不需要:

switcherListItemsAnchors.forEach((switcherListItemAnchor) => {
  switcherListItemAnchor.addEventListener('mouseenter', simulateClick.bind(switcherListItemAnchor))
  switcherListItemAnchor.addEventListener('click', (e) => {
    if (!e.isTrusted) {
      e.stopPropagation();
    }
  })
});
Run Code Online (Sandbox Code Playgroud)
const output = document.querySelector('.output');
const switcherList = document.querySelector('[data-custom-switcher]');

switcherList.querySelectorAll('a').forEach((switcherListItemAnchor) => {
  switcherListItemAnchor.addEventListener('mouseenter', simulateClick)
  switcherListItemAnchor.addEventListener('click', (e) => {
    if (!e.isTrusted) {
      e.stopPropagation();
    }
  })
});
switcherList.querySelectorAll('li').forEach(switcherListItem => {
  switcherListItem.addEventListener('click', activateAnchor);
});

// This should only fire when each item is clicked, but it fires on hover.
function activateAnchor() {
  addMessage('activateAnchor');
}

// This should fire when each item is hovered
function simulateClick(e) {
  this.click();
  addMessage('simulateClick');
}

function addMessage(message) {
  if (message === 'activateAnchor') {
    output.innerHTML += `<h1>This is the activateAnchor function</h1>`;
  }
  if (message === 'simulateClick') {
    output.innerHTML += `<h1>This is the simulateClick function</h1>`;
  }
}
Run Code Online (Sandbox Code Playgroud)
* {
  padding: 0;
  margin: 0;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  height: 100vh;
  font-family: sans-serif;
  font-size: 100%;
}

.output {
  width: 100%;
  background-color: yellow;
}

ul {
  display: flex;
  list-style: none;
}

li+li {
  margin-left: 20px;
}

a {
  padding: 20px;
  background-color: pink;
  transition: background-color .5s ease-in-out;
  text-decoration: none;
  color: #000;
}

a:hover {
  background-color: #ddd;
}
Run Code Online (Sandbox Code Playgroud)