每次Knockout.js后刷新iScrollView

tquggr8v  于 2022-11-10  发布在  其他
关注(0)|答案(2)|浏览(159)

我正在用jQuery移动的/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来完成这样的事情。

44u64gxh

44u64gxh1#

只需插入这一行:

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

ifsvaxew2#

所以这比我想象的要简单得多,我意识到发生的事情是我的图像还没有加载到内存中,这意味着由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(); 
                    });         
            },

比可能会优化一些更多,但它是一个工作的解决方案...

相关问题