在Knockout.js foreach之后刷新iScrollView

时间:2013-02-19 22:21:42

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

初学者使用淘汰赛,尝试一下我们是否可以使用它......请光临我......

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

现在我想使用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来完成这样的事情......

在这种情况下,任何建议或批评都会受到赞赏......

谢谢..

2 个答案:

答案 0 :(得分:0)

只需插入此行:

$('#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');
},

答案 1 :(得分:0)

所以这比我想象的要简单得多,我意识到发生的事情是我的图像还没有加载到内存中,这意味着Knockout生成的标记没有处理图像应该给出的音量。我输入了从本地来源拍摄的填充图像,但它们不一定具有正确的尺寸,我可能最终得到不精确的滚动高度。

我尝试并最终完成的工作是在将图像添加到ko.Observablearray之前预先加载图像。所以我把这个simpe图像预加载器写成了一个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(); 
                    });         
            },

可能会进一步优化,但这是一个有效的解决方案......