【问题标题】:Refresh iScrollView after Knockout.js foreach在 Knockout.js foreach 之后刷新 iScrollView
【发布时间】:2013-02-04 19:04:26
【问题描述】:

我正在使用 jQuery Mobile/Knockout.js/iScrollView 构建一个 Web 应用程序。我有一个使用 Knockout.js foreach 填写的列表。我发出一个 ajax 请求,我得到一个 JSON 对象,我将它推送到我的 observable 数组中,并且我的页面通过向我显示我需要的所有内容来更新。

现在我想使用 iScrollView,以便随着列表的增长,我可以顺利向下滚动并利用上拉或下拉功能。

我似乎无法找出在正确时间调用$(element).iscrollview('refresh') 的正确方法,以便在添加更多项目后调整滚动窗口的大小。

有没有办法等到所有项目都插入到 DOM 中,然后调用 $(element).iscrollview('refresh')

这是我的 HTML

<div data-role="page" id="List" data-bind="event: {pageshow: loadItems}">
      <div data-role="content" data-iscroll>
      <button value='load' data-bind="event: {click: loadItems}">load more stuff</button>
        <ul data-role="none" class="list" data-bind="foreach: items">
            <li style="visibility:hidden">
                <div class="header">
                    <h3 data-bind="text: name"></h3>
                    <p></p> 
                </div>
                <div class="feat-list-btn feat-list-action">
                    <img src="image.png" />
                </div>
                <div class="feat-list-btn feat-list-comments">
                    <img src="image.png" />
                </div>
                    <img data-bind="attr: {src: imageurl}" />
            </li>
        </ul>
      </div>
</div>

这是我获取内容的方式:

function List(){
    var self = this;
    self.loadItems = function(){
        $('#List [data-role="content"]').fadeOut(0);
        $.mobile.showPageLoadingMsg();
            jQuery.ajax({
                url: mybackend.php',
                type: 'POST',
                data: 'howMany=10',
                dataType: 'jsonp',
                jsonp: 'jsoncallback',
                success: function(data, textStatus, jqXHR){
                        for (i=0;i<data.items.length;i++){
                            self.items.push(data.items[i]);
                            }   
                    },
                complete: function(){
                    $.mobile.hidePageLoadingMsg();
                    }
                });
        };
    self.items = ko.observableArray();
    self.updateScroller = function(){
        //????????
        };
    }

我可以解决这个问题

setTimeout(function(){$('#List [data-role="content"]').iscrollview('refresh');}, 1000);

但我宁愿不依赖 setTimeOut 来完成这样的事情。

【问题讨论】:

    标签: ajax cordova jquery-mobile knockout.js iscroll


    【解决方案1】:

    只需插入这一行:

    $('#List [data-role="content"]').iscrollview('refresh');
    

    for循环成功回调之后:

    success: function(data, textStatus, jqXHR){
        for (i=0;i<data.items.length;i++){
            self.items.push(data.items[i]);
        }
        $('#List [data-role="content"]').iscrollview('refresh');
    },
    

    【讨论】:

    • 几乎...我昨晚想通了,我会在一秒钟内发布答案...这将导致在图像加载之前编写标记,这意味着我的 iScroll 将调整到包含 NO 图像的此标记的大小...太短了
    【解决方案2】:

    所以这比我想象的要简单得多,我意识到正在发生的事情是我的图像尚未加载到内存中,这意味着由 Knockout 生成的标记没有图像应该提供体积的地方。我放入了从本地来源获取的填充图像,但它们不一定具有正确的尺寸,并且我最终可能会得到一个不精确的滚动高度。

    我尝试并最终成功的是在将图像添加到 ko.Observablearray 之前预加载图像。所以我把这个简单的图像预加载器写成一个 jQuery 插件:

    (function($) {
        $.fn.preload = function( callback ) {           
            var count = 0,
                $this = this;
            for (i=0;i<this.length;i++){        
                var image = new Image();        
                $(image).on('load error', function(e){count++; if (count === $this.length){if ($.isFunction(callback)){callback.call()}}});
                image.src = this[i];;
                }
            }
        })(jQuery); 
    

    这基本上可以让我等到所有图像都加载到内存中

    然后我添加到我的 ko.Observablearray,它将我的标记与图像插入到位......然后像这样调用 REFRESH:

            success: function(data, textStatus, jqXHR){
                var myImages = [];
                for (i=0;i<data.urls.length;i++){
                    myImages.push(data.urls[i]);
                    }
                    $(myImages).preload(function(){ //only execute insertion after all images are preloaded into memory
                        for (i=0;i<data.items.length;i++){
                            self.items.push(data.items[i]);
                            }   
                            $('#featList [data-role="content"]').iscrollview('refresh');//refresh iScroll
                            $.mobile.hidePageLoadingMsg(); 
                        });         
                },
    

    也许可以再优化一些,但这是一个可行的解决方案......

    【讨论】:

      猜你喜欢
      • 2015-03-29
      • 1970-01-01
      • 2016-08-25
      • 2012-06-10
      • 2013-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多