捕获鼠标滚轮事件作为原生 HTML 属性

Capture mouse wheel event as native HTML attribute

我即将开始处理鼠标滚轮事件,但我在网上唯一能找到的是使用 addEventListener()。我想检测是原生 HTML 和 CSS。换句话说,我正在寻找类似的东西:

<span id='fooBar' onmousewheel='alert("fooBar")'></span>

我正在动态创建 span 并将它们注入 DOM,如果我不必 运行 javascript 这样做,效果会更好。我似乎可以在本机工作但不是鼠标滚轮的所有其他事件。这可能吗?

你只找到对 addEventListener() 的引用的原因是因为那是 standard 和正确的方法(看起来 onmousewheel 在 Firefox 中甚至不被支持)。

虽然可以使用您在问题中显示的代码使其工作(在支持它的浏览器中)(除了您的 span 是空的,所以您不能用它启动事件,因为元素不会有任何渲染大小),我在下面有一个例子,内联 HTML 事件处理属性的使用让人回想起我们有标准之前的时间,不应该使用。 Here's a link 我的另一个回答解释了原因。

<span id='fooBar' onmousewheel='alert("fooBar")'>Use the mousewheel while mouse is over this</span>

您可以非常轻松地动态创建带有侦听器的元素。您只需要了解 DOM 以及如何附加事件侦听器。

下面的示例创建了 10 个跨度并为每个跨度附加了一个侦听器。只需将鼠标悬停在一个跨度上并滚动鼠标滚轮。跨度的 ID 将记录到控制台。

// Create 10 spans with a scroll listener.
var count = 10;
for (var i = 0; i < count; i++) {
  var span = document.createElement('SPAN');
  span.id = 'foo-bar-' + i;
  span.innerHTML = 'Foo #' + i;
  addEventListener(span, 'mousewheel', performEvent);
  document.body.appendChild(span);
}

// Event function.
function performEvent(e) {
  console.log(e.target.id);
}

// IE 8+ via http://youmightnotneedjquery.com/
function addEventListener(el, eventName, handler) {
  if (el.addEventListener) {
    el.addEventListener(eventName, handler);
  } else {
    el.attachEvent('on' + eventName, function(){
      handler.call(el);
    });
  }
}
.as-console-wrapper { max-height: 5em !important; }

span[id^="foo-bar-"] {
  border: thin solid black;
  margin: 0.25em;
}

尝试以下操作:

::-webkit-scrollbar {
    width: 0px;  /* remove scrollbar space */
    background: transparent;  /* optional: just make scrollbar invisible */
}
<!DOCTYPE HTML>
<html>
  <body style="overflow: auto;
max-height: 100vh;" onscroll="alert('hi')">
    <div style="height:2000px;width:100%"></div>
  </body>
</html>

你只找到 "addEventListener" 个例子的原因是你需要处理这个跨浏览器:

var supportedWheelEvent = "onwheel" in HTMLDivElement.prototype ? "wheel" : document.onmousewheel !== undefined ? "mousewheel" : "DOMMouseScroll";

此外,最好只对一个元素执行此操作!使用委托事件侦听器来处理您需要的所有元素。

HTML 示例:

<div id="delegator">
   <div class="handleWheel">handle wheel event here</div>
   <div> no wheel event handled here </div>
   <div class="handleWheel">handle wheel event here</div>
   <div> no wheel event handled here </div>
</div>

JS:

var supportedWheelEvent = "onwheel" in HTMLDivElement.prototype ? "wheel" : document.onmousewheel !== undefined ? "mousewheel" : "DOMMouseScroll";

function handler(e){
    if(e.target.classList.contains('handleWheel')){
        // handle the event here
    }
}

var d = document.getElementById('delegator');
d.addEventListener(supportedWheelEvent, handler);

工作代码笔示例: https://codepen.io/Mchaov/pen/zwaMmM

内联与委派

在演示中,A 方使用标准 addEventListener 并注册 wheel 事件,该事件是已弃用的 mousewheel 事件的替代品。使用 addEventListener 不仅是标准,而且如果使用 event delegation 则效率最高。

使用 onwheel 作为属性事件的支持有限,因为使用任何属性事件都是非标准的并且不鼓励使用。尽管如此,我还是包含了 B 面,它使用已弃用的非标准 onmousewheel 事件作为属性内联事件处理程序。因为它是一个笨拙的编码 <span>,所以我在使用所有三个引号(即 '"、`)的字符串上使用了 insertAdjacentHTML。在第二层嵌套引号中使用了字符串文字,非常混乱。

请参阅此 post,了解如何在事件委托中使用事件对象属性。

详情在demo中评论

演示

// Reference the buttons 
const btnA = document.getElementById('addA');
const btnB = document.getElementById('addB');

// Reference the parent nodes
const secA = document.querySelector('section:first-of-type');
const secB = document.querySelector('section:last-of-type');

// Register the click event on buttons
btnA.addEventListener('click', addNodeA, false);
btnB.addEventListener('click', addNodeB, false);

/* Register the wheel event on section A 
|| which is the parent node of the wheeled
|| nodes. Event delegation involves one 
|| event handler for multiple event targets.
|| This is far more efficient than multiple 
|| inline event handlers.
*/
secA.addEventListener('wheel', markNode, false);

let cnt = 0;

/* Add node A to section A
|| ex. <span id="A1" class="A">A1</span>
*/
function addNodeA(e) {
  cnt++;
  var nodeA = document.createElement('span');
  nodeA.id = 'A' + cnt;
  nodeA.textContent = nodeA.id;
  nodeA.className = 'A';
  secA.appendChild(nodeA);
  return false;
}

/* Add node B to section B
|| ex. <span id="B3" class="B" onmousewheel="this.style.outline = `5px dashed red`">B3</span>
*/
function addNodeB(e) {
  cnt++;
  /* This string is wrapped in single quotes,
  || double quotes for the attributes values,
  || and backticks for the property value of
  || an attribute value. Very messy, confusing,
  || and inefficient.
  */
  var nodeB = '<span id="B' + cnt + '" class="B" onmousewheel="this.style.outline = `5px dashed red`">B' + cnt + '</span>';

  // insertAdjacentHTML is innerHTML on steroids
  secB.insertAdjacentHTML('beforeend', nodeB);
  return false;
}

function markNode(e) {

  /* If the wheeled node (i.e. e.target) is not the 
  || registered node (i.e. e.currentTarget), then...
  */
  if (e.target !== e.currentTarget) {
    var node = e.target;
    if (node.className === 'A') {
      node.style.outline = '5px dashed blue';
    } else {
      return false;
    }
  }
}
html,
body {
  width: 100%;
  width: 100%
}

fieldset {
  height: 10%;
}

main {
  border: 3px solid lime;
  height: 90%;
  min-height: 250px;
  display: flex;
}

section {
  width: 50%;
  min-height: 250px;
  outline: 3px dashed gold;
  padding: 10px 25px;
}

span {
  height: 50px;
  width: 50px;
  padding: 2px;
  text-align: center;
  font-size: 12px;
  margin: 5px;
  display: inline-block;
}

.A {
  background: rgba(0, 100, 200, .3);
}

.B {
  background: rgba(200, 100, 0, .3);
}

#addB {
  margin-left: 35%
}
<fieldset>
  <legend>addNode</legend>
  <button id='addA'>nodeA</button>
  <button id='addB'>nodeB</button>
</fieldset>
<main>
  <section></section>
  <section></section>
</main>