滚动事件侦听器 javascript

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12522807/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 10:36:53  来源:igfitidea点击:

Scroll event listener javascript

javascript

提问by Kpower

Is there a js listener for when a user scrolls in a certain textbox that can be used? Kinda like onclick except for scrolling. I saw HTML5 event listener for number input scroll - Chrome onlybut that seems to be for chrome only. I'm looking for something cross-browser.

当用户在可以使用的某个文本框中滚动时,是否有 js 侦听器?除了滚动,有点像 onclick。我看到了用于数字输入滚动的 HTML5 事件侦听器 - 仅适用于 Chrome,但这似乎仅适用于 chrome。我正在寻找跨浏览器的东西。

回答by Mike 'Pomax' Kamermans

For those who found this question hoping to find an answer that doesn't involve jQuery, you hook into the window"scroll" event using normal event listening. Say we want to add scroll listening to a number of CSS-selector-able elements:

对于那些发现这个问题希望找到不涉及 jQuery 的答案的人,您可以window使用正常的事件侦听挂钩到“滚动”事件。假设我们要添加滚动监听一些 CSS-selector-able 元素:

// what should we do when scrolling occurs
var runOnScroll =  function(evt) {
  // not the most exciting thing, but a thing nonetheless
  console.log(evt.target);
};

// grab elements as array, rather than as NodeList
var elements = document.querySelectorAll("...");
elements = Array.prototype.slice.call(elements);

// and then make each element do something on scroll
elements.forEach(function(element) {
  window.addEventListener("scroll", runOnScroll, {passive: true});
});

(Using the passiveattribute to tell the browser that this event won't interfere with scrolling itself)

(使用passive属性告诉浏览器这个事件不会干扰滚动本身)

For bonus points, you can give the scroll handler a lock mechanism so that it doesn't run if we're already scrolling:

对于奖励积分,您可以为滚动处理程序提供一个锁定机制,以便在我们已经在滚动时它不会运行:

// global lock, so put this code in a closure of some sort so you're not polluting.
var locked = false;
var lastCall = false;

var runOnScroll =  function(evt) {
  if(locked) return;

  if (lastCall) clearTimeout(lastCall);
  lastCall = setTimeout(() => {
    runOnScroll(evt);
    // you do this because you want to handle the last
    // scroll event, even if it occurred while another
    // event was being processed.
  }, 200);

  // ...your code goes here...

  locked = false;
};

回答by Naomi Fridman

I was looking a lot to find a solution for sticy menue with old school JS (without JQuery). So I build small test to play with it. I think it can be helpfull to those looking for solution in js. It needs improvments of unsticking the menue back, and making it more smooth. Also I find a nice solution with JQuery that clones the original div instead of position fixed, its better since the rest of page element dont need to be replaced after fixing. Anyone know how to that with JS ? Please remark, correct and improve.

我一直在寻找使用老式 JS(没有 JQuery)解决 sticy menue 的解决方案。所以我建立了一个小测试来玩它。我认为它可以帮助那些在 js 中寻找解决方案的人。它需要改进菜单,使其更光滑。我还找到了一个很好的 JQuery 解决方案,它克隆原始 div 而不是固定位置,它更好,因为修复后不需要替换页面元素的其余部分。任何人都知道如何用 JS 做到这一点?请大家评论、纠正和改进。

<!DOCTYPE html>
<html>

<head>
<script>

// addEvent function by John Resig:
// http://ejohn.org/projects/flexible-javascript-events/

function addEvent( obj, type, fn ) {

    if ( obj.attachEvent ) {

        obj['e'+type+fn] = fn;
        obj[type+fn] = function(){obj['e'+type+fn]( window.event );};
        obj.attachEvent( 'on'+type, obj[type+fn] );
    } else {
        obj.addEventListener( type, fn, false );
    }
}
function getScrollY() {
    var  scrOfY = 0;
    if( typeof( window.pageYOffset ) == 'number' ) {
        //Netscape compliant
        scrOfY = window.pageYOffset;

    } else if( document.body && document.body.scrollTop )  {
        //DOM compliant
        scrOfY = document.body.scrollTop;
    } 
    return scrOfY;
}
</script>
<style>
#mydiv {
    height:100px;
    width:100%;
}
#fdiv {
    height:100px;
    width:100%;
}
</style>
</head>

<body>

<!-- HTML for example event goes here -->

<div id="fdiv" style="background-color:red;position:fix">
</div>
<div id="mydiv" style="background-color:yellow">
</div>
<div id="fdiv" style="background-color:green">
</div>

<script>

// Script for example event goes here

addEvent(window, 'scroll', function(event) {

    var x = document.getElementById("mydiv");

    var y = getScrollY();      
    if (y >= 100) {
        x.style.position = "fixed"; 
        x.style.top= "0";
    } 
});

</script>
</body>
</html>

回答by Satya

Wont the below basic approach doesn't suffice your requirements?

下面的基本方法不能满足您的要求吗?

HTML Code having a div

具有 div 的 HTML 代码

<div id="mydiv" onscroll='myMethod();'>


JS will have below code


JS将有以下代码

function myMethod(){ alert(1); }

回答by Josh Habdas

Is there a js listener for when a user scrolls in a certain textbox that can be used?

当用户在可以使用的某个文本框中滚动时,是否有 js 侦听器?

DOM L3 UI Eventsspec gave the initial definition but is consideredobsolete.

DOM L3 UI Events规范给出了最初的定义,但被认为已经过时。

To add a single handler you can do:

要添加单个处理程序,您可以执行以下操作:

  let isTicking;
  const debounce = (callback, evt) => {
    if (isTicking) return;
    requestAnimationFrame(() => {
      callback(evt);
      isTicking = false;
    });
    isTicking = true;
  };
  const handleScroll = evt => console.log(evt, window.scrollX, window.scrollY);
  document.defaultView.onscroll = evt => debounce(handleScroll, evt);

For multiple handlers or, if preferable for style reasons, you may use addEventListeneras opposed to assigning your handler to onscrollas shown above.

对于多个处理程序,或者如果出于样式原因更可取,您可以使用addEventListener而不是将处理程序分配给onscroll如上所示。

If using something like _.debouncefrom lodash you could probably get away with:

如果使用_.debouncelodash 之类的东西,你可能会逃脱:

const handleScroll = evt => console.log(evt, window.scrollX, window.scrollY);
document.defaultView.onscroll = evt => _.debounce(() => handleScroll(evt));

Review browser compatibilityand be sure to test on some actual devices before calling it done.

检查浏览器兼容性,并确保在完成之前在某些实际设备上进行测试。