是否有一个js监听器可以用来检测用户在特定文本框中滚动的事件,就像onclick一样,但是针对滚动操作。我看到了 HTML5事件侦听器 适用于数字输入滚动-仅限Chrome ,但这似乎只适用于Chrome。我正在寻找跨浏览器的解决方案。
是否有一个js监听器可以用来检测用户在特定文本框中滚动的事件,就像onclick一样,但是针对滚动操作。我看到了 HTML5事件侦听器 适用于数字输入滚动-仅限Chrome ,但这似乎只适用于Chrome。我正在寻找跨浏览器的解决方案。
对于那些希望找到不涉及jQuery的答案的人,你可以使用普通事件监听来钩入window
的“scroll”事件。假设我们想要将滚动监听添加到多个可通过CSS选择器选择的元素中:
// what should we do when scrolling occurs
function runOnScroll(element) {
// not the most exciting thing, but a thing nonetheless
console.log(element);
};
// grab elements as array, rather than as NodeList
const elements = document.querySelectorAll(`...`);
// and then make each element do something on scroll
elements.forEach(element => {
window.addEventListener(
"scroll",
() => runOnScroll(element),
{ passive: true }
);
});
或者,您可以绑定一个单一的滚动监听器,将evt => runOnScroll(evt)
作为处理程序,然后在runOnScroll
函数中确定对elements
中的所有内容要执行什么操作。
请注意,我们使用了passive属性来告诉浏览器,该事件不会干扰滚动本身。如果我们想要平滑的滚动行为(并且这也意味着我们不应该在滚动期间执行重新流程触发的DOM更新),这很重要。
作为额外加分项,您可以给滚动处理程序添加锁定机制,以便在我们已经滚动时它不会运行:
// global lock, so put this code in a closure of some sort so you're not polluting.
let locked = false;
let lastCall = false;
function runOnScroll(element) {
if(locked) return;
if (lastCall) clearTimeout(lastCall);
lastCall = setTimeout(() => {
runOnScroll(element);
// 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;
};
useCapture
是一种确保处理程序在任何处理程序由于冒泡而获取事件之前触发的方法,或者是“我不关心它被调用的顺序”。然而,对于这个目的来说并不太有用,因为当使用多个具有 useCapture=true
的侦听器时,没有调用顺序保证。 - Mike 'Pomax' Kamermansfunction(element)
,它接受element
作为参数,但是这个变量从来没有被使用过?你总是将事件监听器添加到window
上。 - oliversisson<!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>
<div id="mydiv" onscroll='myMethod();'>
JS将有以下代码
function myMethod(){ alert(1); }
myMethod
是否是全局的—— window.myMethod
;)。 - Maxime Dupré 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);
如果有多个处理程序或者出于样式原因更喜欢的话,可以使用 addEventListener
而不是像上面所示那样将处理程序分配给 onscroll
。
如果使用类似于 lodash 的 \_.debounce
,你可能可以轻松搞定:
const handleScroll = evt => console.log(evt, window.scrollX, window.scrollY);
document.defaultView.onscroll = evt => _.debounce(() => handleScroll(evt));
请查看浏览器兼容性,并在完成前务必在一些实际设备上进行测试。
let lastKnownScrollPosition = 0;
let ticking = false;
function doSomething(scrollPos) {
// Do something with the scroll position
}
document.addEventListener('scroll', function(e) {
lastKnownScrollPosition = window.scrollY;
if (!ticking) {
window.requestAnimationFrame(function() {
doSomething(lastKnownScrollPosition);
ticking = false;
});
ticking = true;
}
});