【发布时间】:2015-12-18 09:03:25
【问题描述】:
我有一个设置,其中有一个标题,仅当可滚动区域的 scrollTop 为 0 时才会显示(意味着它们位于页面顶部)。这在许多情况下似乎都可以正常工作,但在某些情况下它会以一种相当烦人的方式失败。
虫子
如果可滚动区域中的内容稍微大到足以形成滚动条,那么当您向下滚动时,标题将消失,可滚动区域现在将增大以填充该空白空间,这将允许内容在没有滚动条的情况下出现。 从有滚动条到没有滚动条的转换显然会在我测试过的所有浏览器中触发另一个滚动事件我不知道这是为什么或如何解决它。
一种可能的解决方案
我可以将我的内容设置为 101% 的最小高度,这样无论实际内容高度是多少,滚动条都会一直存在。然而,这不是我最喜欢的解决方案,我正在寻找更好的解决方案。
html
<div class="container">
<div class="header">Header</div>
<div class="content" data-bind="css: {'show-header': showHeader}">
<div class="sub-header">Sub Header</div>
<div class="scrollable" data-bind="event: {'scroll':test}">
<div class="stuff">asdf</div>
</div>
</div>
CSS
.container {
position: absolute;
top: 0;
left: 0;
width: 320px;
height: 352px;
border: 1px solid black;
}
.header {
height: 48px;
background: grey;
}
.content {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
transition: top 0.3s;
}
.show-header {
top: 48px;
}
.sub-header {
height: 48px;
background: lightgrey;
}
.scrollable {
position: absolute;
top: 48px;
left: 0;
right: 0;
bottom: 0;
overflow: auto;
-webkit-overflow-scrolling: touch;
overflow-x: hidden;
}
.stuff {
/*min-height: 101%;*/
height: 260px;
/*height: 2000px;*/
}
JS
var appViewModel = {};
var didScroll = false;
var scrollElem = $('.scrollable');
appViewModel.showHeader = ko.observable(true);
appViewModel.test = function() {
didScroll = true;
};
setInterval(function() {
if (didScroll) {
didScroll = false;
appViewModel.hasScrolled();
}
}, 250);
appViewModel.hasScrolled = function() {
var st = scrollElem.scrollTop();
if ( st > 0 && appViewModel.showHeader() ) {
appViewModel.showHeader(false);
}
else if ( st <= 0 && !appViewModel.showHeader() ) {
appViewModel.showHeader(true);
}
};
ko.applyBindings(appViewModel);
JS 小提琴 JS Fiddle Example
【问题讨论】:
-
为什么要检查间隔而不是'onscroll'事件的滚动?
-
性能原因。基本上你不应该在滚动事件本身上执行繁重的代码,因为它会被触发很多次。所以最好(特别是对于移动设备)设置一个标志(这在处理器上并不难),然后使用该标志通过间隔进行检查。来源:ejohn.org/blog/learning-from-twitter
-
您可以检查溢出内容的高度是否小于您的标题,因此您可以添加一个标志以避免标题的隐藏行为。
-
引用:“相反,最好使用某种形式的计时器每隔 X 毫秒检查一次,或者附加一个滚动事件并仅在延迟后运行您的代码。”您链接的文章讨论了滚动事件处理程序中的密集选择器。我会在这里选择延迟并设置一个转换标志,因为它可以防止来自间隔的不需要的触发器。也许这是一个 CSS 问题。
标签: javascript jquery html css knockout.js