javascript – 在分配滚动侦听器之前更新scrollTop会触发滚动事件
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了javascript – 在分配滚动侦听器之前更新scrollTop会触发滚动事件,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7820字,纯文字阅读大概需要12分钟。
内容图文
![javascript – 在分配滚动侦听器之前更新scrollTop会触发滚动事件](/upload/InfoBanner/zyjiaocheng/767/0f35ccbc9f67421eb0a190ab1557c33e.jpg)
在我开始收听滚动事件之前,我正在更新元素的scrollTop.但是,滚动事件会触发,即使它是在scrollTop更新后添加的.
我注意到,如果我将.onscroll赋值包装在setTimeout(…,1)中;它运作得很好.
另请注意,在输出中,内存中的scrollTop值不会更改,但它会触发事件.
starting out 0
haven’t added listener yet 100
listener added 100
scrolled 100
任何人都可以解释为什么这样的工作?使用setTimeout或设置标志似乎是一种解决这个问题的方法;有没有更好的办法?
var div = document.getElementsByTagName('div')[0];
console.log("starting out", div.scrollTop);
div.scrollTop = 100;
console.log("haven't added listener yet", div.scrollTop);
div.onscroll = function() {
console.log('scrolled', div.scrollTop);
};
console.log("listener added", div.scrollTop);
div {
width: 80%;
height: 200px;
margin: 20px auto;
overflow: auto;
padding: 20px;
box-sizing: border-box;
border: 1px solid black;
}
<div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi id mi sit amet tortor suscipit sagittis at id risus. Nullam ultricies nisi ac tortor ultrices porta. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nam purus sapien, efficitur in risus non, cursus egestas lectus. Curabitur pharetra erat sapien, et malesuada neque mollis nec. Donec dolor lacus, pretium eu ipsum sit amet, placerat vehicula orci. Sed viverra metus id magna sodales, et condimentum urna sagittis. Donec a viverra urna. Pellentesque lacinia commodo ligula sed porttitor. Aliquam iaculis diam nec nibh congue congue. Nunc eget dapibus orci, ac tristique nunc. Mauris nisl tellus, posuere sed lectus sit amet, vulputate sollicitudin magna. Nullam porttitor leo bibendum, varius libero vitae, ultrices diam. Donec mauris nulla, egestas non nisi sit amet, ultricies laoreet sapien.</p>
<p>Vivamus mollis placerat felis ut porta. Pellentesque pellentesque blandit leo, fermentum sollicitudin risus porta quis. Phasellus gravida justo nec mi accumsan, in euismod tortor venenatis. Donec porttitor consequat dui ac iaculis. Quisque scelerisque dictum risus, eu gravida nibh sodales in. Vivamus sit amet consectetur urna. Aliquam quis pretium turpis, non rhoncus lectus. Ut vel mi urna. Mauris interdum congue felis ut faucibus. Praesent nec lobortis enim. Vestibulum velit nisl, dapibus vulputate interdum vitae, sagittis a nisl.</p>
<p>Donec consectetur justo a purus sodales, quis ultrices enim sodales. Sed fermentum congue enim vehicula volutpat. Proin pellentesque elit et dolor congue, in blandit tellus aliquet. Cras tincidunt metus lorem, et tincidunt arcu condimentum eget. Curabitur sed ipsum nec erat mollis volutpat eget eget purus. Nam nec eleifend est. Sed ut elit eget odio mollis dignissim vitae nec urna. In vel libero eget libero rutrum consectetur non eget dui. Proin dignissim convallis elit, id mollis metus sodales eget. Aliquam non iaculis justo. Aenean vel diam nibh. Nam euismod viverra ante, ac molestie sem. Donec cursus justo a sagittis iaculis. Sed at maximus lacus, sit amet gravida mauris. Curabitur non odio at ipsum consequat fermentum. Morbi vestibulum nec dui id tincidunt.</p>
<p>Integer nec nunc ultricies, mattis leo sed, gravida enim. In hac habitasse platea dictumst. Nunc sed turpis sed nisi consequat faucibus. Fusce sagittis maximus luctus. Maecenas at tortor blandit, imperdiet ligula vel, vestibulum diam. Proin consequat sodales nisl, quis varius erat semper vitae. Etiam ac pretium lacus. Phasellus in vestibulum tellus, nec tempus dolor. Etiam fringilla convallis rhoncus. Sed id enim erat. Integer congue orci sapien, ac porttitor arcu pellentesque eget. Mauris eu rutrum urna. Donec ante eros, scelerisque id ipsum et, pulvinar dapibus erat.</p>
<p>Fusce eget bibendum eros. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec finibus justo a neque hendrerit, imperdiet fringilla nibh tincidunt. Etiam consequat a erat fringilla volutpat. Proin porttitor nec sem non semper. Suspendisse sollicitudin erat eu urna gravida volutpat quis sit amet leo. Mauris luctus purus eget purus mattis semper. Curabitur ut ante fringilla, porta neque non, hendrerit diam. Morbi dignissim congue orci ac vestibulum. Vestibulum ipsum urna, faucibus nec venenatis eu, efficitur vitae massa. Suspendisse lectus lorem, molestie vel consequat eget, malesuada sed turpis. Curabitur sit amet ipsum et justo sollicitudin pretium. Praesent dignissim, mauris ut hendrerit egestas, massa orci cursus justo, non porta metus erat et velit. Curabitur vitae orci eu erat ultrices aliquet.</p>
</div>
解决方法:
我想这是因为浏览器直到下一帧才进行实际滚动.因此,在滚动甚至更新之前设置事件侦听器.
你可以做些什么来避免它是忽略第一个滚动事件.
var scrolled = false;
window.scrollTo(0, 100);
window.addEventListener('scroll', function() {
if(!scrolled) {
scrolled = true;
return;
}
// Do stuff...
});
编辑以反映OP的评论:
我无法想象为什么这对你不起作用:
window.scrollTo(0, 100);
window.addEventListener('scroll', function() {
if(typeof window.scrollEventHasFired === "undefined") {
window.scrollEventHasFired = true;
return;
}
// Do stuff...
});
进一步编辑,反映新信息:
这对你有用吗?这允许设置多个事件,并允许在事件之外调用侦听器:
var scrolled = [false],
id = 0;
var listener = function(skipFirstExec, listenerId, args...) {
if(skipFirstExec && !scrolled[listenerId]) {
scrolled[listenerId] = true;
return;
}
// Do stuff
};
window.addEventListener('scroll', listener.bind(thisArg, true, ++id));
scrolled[id] = false;
window.addEventListener('scroll', listener.bind(thisArg, false, ++id)); // This one won't skip the scroll
scrolled[id] = false;
window.addEventListener('scroll', listener.bind(thisArg, true, ++id));
scrolled[id] = false;
listener(false, 0, args...); // call listener outside of event
最终编辑:
这对我有用,不知道为什么我之前没有想到这个:
/**
* requestAnimationFrame polyfill by Erik M?ller & Paul Irish et. al.
* https://gist.github.com/1866474
*
* http://paulirish.com/2011/requestanimationframe-for-smart-animating/
* http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
**/
/*jshint asi: false, browser: true, curly: true, eqeqeq: true, forin: false, newcap: true, noempty: true, strict: true, undef: true */
(function( window ) {
'use strict';
var lastTime = 0;
var prefixes = 'webkit moz ms o'.split(' ');
// get unprefixed rAF and cAF, if present
var requestAnimationFrame = window.requestAnimationFrame;
var cancelAnimationFrame = window.cancelAnimationFrame;
// loop through vendor prefixes and get prefixed rAF and cAF
var prefix;
for( var i = 0; i < prefixes.length; i++ ) {
if ( requestAnimationFrame && cancelAnimationFrame ) {
break;
}
prefix = prefixes[i];
requestAnimationFrame = requestAnimationFrame || window[ prefix + 'RequestAnimationFrame' ];
cancelAnimationFrame = cancelAnimationFrame || window[ prefix + 'CancelAnimationFrame' ] ||
window[ prefix + 'CancelRequestAnimationFrame' ];
}
// fallback to setTimeout and clearTimeout if either request/cancel is not supported
if ( !requestAnimationFrame || !cancelAnimationFrame ) {
requestAnimationFrame = function( callback, element ) {
var currTime = new Date().getTime();
var timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
var id = window.setTimeout( function() {
callback( currTime + timeToCall );
}, timeToCall );
lastTime = currTime + timeToCall;
return id;
};
cancelAnimationFrame = function( id ) {
window.clearTimeout( id );
};
}
// put in global namespace
window.requestAnimationFrame = requestAnimationFrame;
window.cancelAnimationFrame = cancelAnimationFrame;
})( window );
(function() {
var div = document.getElementsByTagName('div')[0];
console.log("starting out", div.scrollTop);
div.scrollTop = 100;
console.log("haven't added listener yet", div.scrollTop);
window.requestAnimationFrame(function() {
div.onscroll = function() {
console.log('scrolled', div.scrollTop);
};
console.log("listener added", div.scrollTop);
});
})();
内容总结
以上是互联网集市为您收集整理的javascript – 在分配滚动侦听器之前更新scrollTop会触发滚动事件全部内容,希望文章能够帮你解决javascript – 在分配滚动侦听器之前更新scrollTop会触发滚动事件所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。