无限滚动显式设置scrollTop时,在iOS webkit浏览器上闪烁

时间:2014-07-21 11:31:23

标签: javascript jquery ios scrolltop

我有一个奇怪的问题,很难解释。我仍然会继续尝试。发生的事情是我有一个无限滚动逻辑,当用户滚动到页面底部时我加载更多内容,如果DOM元素的数量增加超过一定限度,我从顶部删除一个相等的DOM元素块,保持页面中的DOM元素不变,并保持内存的检查。现在,当我在底部添加新元素并从顶部删除旧元素时,我必须显式设置可滚动元素(父容器)的scrollTop位置,以维护用户的滚动位置。我正在使用Jquery的scrollTop()方法调用来设置此刻的滚动位置。一旦我通过调用scrollTop()更新滚动位置,页面就会闪烁,我可以在iOS设备上看到短暂的白色补丁。即使使用本机Javacript scrollTop属性也会发生这种情况。这个问题只出现在iOS webkit浏览器上(包括网页浏览器和设备上的浏览器以及模拟器),我在Android网页上看不到同样的问题。即使在桌面浏览器上,它也能正常运行,包括Safari。

我正在编写的代码是双向无限滚动,但对于这个问题,我只发布了向下滚动的代码。

以下是代码段 -

<!doctype html>
<html>
    <head>
        <meta name="viewport" content="width=device-width, user-scalable=no" /> 
        <style type="text/css">
            html, body {
                margin: 0;
                padding: 0;
                height: 100%;
                background: #fff;
            }
            #holder {
                overflow-x: hidden;
                overflow-y: scroll;
                position: absolute;
                top: 0;
                left: 0;
                bottom: 0;
                right: 0;
            }


            ul {
                margin: 0;
                padding: 0;
            }
            ul li {
                list-style: none;
                padding: 20px;
                border-bottom: 1px solid #9a9a9a;
                background: #e5e5e4;
            }
            .androidFix {
              overflow: hidden !important;
              overflow-y: hidden !important;
              overflow-x: hidden !important;
            }
        </style>
    </head>
    <body>
        <div id="holder">
            <div id="container">

            </div>
        </div>

        <!-- Script goes here -->
        <script type="text/javascript" src="jquery-2.0.3.js"></script>
        <script type="text/javascript" src="handlebars.js"></script>

        <!-- Sample data -->
        <script type="text/javascript">
            var data = [{slno: '1', amount: '250', name: 'DAG Account', date: '16/07/2014'},
                        {slno: '2', amount: '250', name: 'DAG Account', date: '16/07/2014'},
                        {slno: '3', amount: '250', name: 'DAG Account', date: '16/07/2014'},
                        {slno: '4', amount: '250', name: 'DAG Account', date: '16/07/2014'},
                        {slno: '5', amount: '250', name: 'DAG Account', date: '16/07/2014'},
                        {slno: '6', amount: '250', name: 'DAG Account', date: '16/07/2014'},
                        {slno: '7', amount: '250', name: 'DAG Account', date: '16/07/2014'},
                        {slno: '8', amount: '250', name: 'DAG Account', date: '16/07/2014'},
                        {slno: '9', amount: '250', name: 'DAG Account', date: '16/07/2014'},
                        {slno: '10', amount: '250', name: 'DAG Account', date: '16/07/2014'}];
        </script>

        <!-- Handlebars template -->
        <script id="template" type="text/x-handlebars-template">
            {{#each data}}
                <li>
                     <div>
                        <span><b>sl no {{slno}}</b></span>
                        <span>{{amount}}</span>
                    </div>
                    <div>
                        <span>{{name}}</span>
                        <span>{{date}}</span>
                    </div>
                </li>
            {{/each}}
        </script>

        <!-- App logic -->
        <script type="text/javascript">

            var source   = $("#template").html();
            var template = Handlebars.compile(source);
            var html = template({data: data});
            //console.log(html);

            var holderRef = $("#holder");
            var holderHeight = $("#holder").height();

            var newChunk = $("<ul class='list-chunk' />");
            newChunk.append(html);

            var containerRef = $("#container");

            containerRef.append(newChunk);  //initial data load

            var chunkHeight = $(".list-chunk").height();


            $("#holder").scroll(function() {

                //test for bottom
                var scrollTopVal = this.scrollTop;

                var containerHeight = containerRef.height();

                //console.log('test', scrollTopVal);

                if(scrollTopVal + holderHeight >= containerHeight) {
                    console.log('bottom');

                    var newChunk = $("<ul class='list-chunk' />");
                    newChunk.append(html);

                    containerRef.append(newChunk);

                    //if($("#container").children().size() > 2) {
                    if(containerRef.children().size() > 2) {
                        var viewTop = $("#holder").scrollTop();

                        var oldChunk = containerRef.children().first();
                        var oldChunkHeight = oldChunk.height();
                        console.log(chunkHeight);
                        oldChunk.remove();

                        setScrollTop(viewTop - chunkHeight);  
                    }

                }


                function setScrollTop(amount) {
                    $("#holder").addClass("androidFix").scrollTop(amount).removeClass("androidFix");   //******* - the problem lies here
                }
            });
        </script>
    </body>
</html>

1 个答案:

答案 0 :(得分:1)

我会按顺序提出一些建议/猜测:

您的androidFix类也正在其他系统上应用。而不是应用类,只在需要它的系统上直接更改元素样式道具(element.style.overflowX =&#34;隐藏&#34;等)。也许是浏览器嗅探。您可以直接在同一个调用中应用您的scrollTop,这样可以节省您必须在滚动设置周围打开类然后关闭,并保存多个昂贵的DOM操作。

滚动事件激发了很多,DOM操作非常缓慢,特别是改变了DOM树。您可以设置一个标志(changingDOM = true),然后直接从后续调用滚动处理程序返回,直到您完成并将其设置为false。

来想一想,这是androidfix的原因吗?设置scrollTop递归调用滚动处理程序,除非你溢出=隐藏?在那种情况下,我会首先尝试后一种变化。