knockout virtual scrolling binding

后端 未结 2 1344
-上瘾入骨i
-上瘾入骨i 2020-12-31 01:06

KOGrid uses virtual scrolling to render content dynamically. I\'m looking for something like that but more generic so it could be used for ul lists, Bootstrap r

相关标签:
2条回答
  • 2020-12-31 01:07

    A simple solution without using a custom binding:

    Fiddler Example: http://jsfiddle.net/adrienne/Y2WUN/

    Markup:

    <div>
        <span data-bind="text: items().length"></span>
        <img src="http://rniemeyer.github.com/KnockMeOut/Images/loading.gif" data-bind="visible: pendingRequest" />
    </div>
    <div id="main" data-bind="foreach: items, event: { scroll: scrolled }">
        <div data-bind="text: name"></div>
    </div>
    

    ViewModel:

    var viewModel = {
        items: ko.observableArray([]),
        scrolled: function(data, event) {
            var elem = event.target;
            if (elem.scrollTop > (elem.scrollHeight - elem.offsetHeight - 200)) {
                getItems(20);
            }
        },
        maxId: 0,
        pendingRequest: ko.observable(false)
    };
    
    
    function getItems(cnt) {
        if (!viewModel.pendingRequest()) {
            //create fake data to pass to echo service
            var entries = [];
            for (var i = 0; i < cnt; i++) {
                var id = viewModel.maxId++;
                entries.push({
                    id: id,
                    name: "Name" + id
                });
            }
    
            viewModel.pendingRequest(true);
    
            $.ajax({
                type: 'POST',
                url: '/echo/json/',
                data: {
                    json: ko.toJSON(entries),
                    delay: .1
                },
                success: function(entries) {
                    ko.utils.arrayForEach(entries, function(entry) {
                        viewModel.items.push(entry);
                    });
                    viewModel.pendingRequest(false);
                },
                error: function() {
                    viewModel.pendingRequest(false);
                },
                dataType: 'json'
            });
        }
    }
    
    ko.applyBindings(viewModel);
    
    getItems(20);
    

    A different solution using a custom binding scrolling the entire browser window:

    http://figg-blog.tumblr.com/post/32733177516/infinite-scrolling-knocked-out.

    Fiddler example: http://jsfiddle.net/8x4vG/2/

    Use the binding like so:

    <div data-bind="foreach: collection">
        <div>
        <span data-bind="text: $index()"></span>
        <span data-bind="text: $data"></span>
        </div>
    </div>
    <div data-bind="scroll: collection().length < 160, scrollOptions: { loadFunc: addSome, offset: 10 }">loading</div>
    

    With a View Model looking something like this:

    var viewModel = function(){            
        this.collection = ko.observableArray([]) 
        var disney = ["Mickey", "Donald", "Daffy", "Hewie", "Dewie", "Lewie"]
        var self = this;
    
        this.addSome = function(){ 
            for(var i = 0; i < 40; i++){
                self.collection.push(disney[Math.floor((Math.random()*6))]) 
            }
        }
    
        this.addSome(); 
    }
    

    The binding implementation:

    ko.bindingHandlers.scroll = {
    
      updating: true,
    
      init: function(element, valueAccessor, allBindingsAccessor) {
          var self = this
          self.updating = true;
          ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
                $(window).off("scroll.ko.scrollHandler")
                self.updating = false
          });
      },
    
      update: function(element, valueAccessor, allBindingsAccessor){
        var props = allBindingsAccessor().scrollOptions
        var offset = props.offset ? props.offset : "0"
        var loadFunc = props.loadFunc
        var load = ko.utils.unwrapObservable(valueAccessor());
        var self = this;
    
        if(load){
          element.style.display = "";
          $(window).on("scroll.ko.scrollHandler", function(){
            if(($(document).height() - offset <= $(window).height() + $(window).scrollTop())){
              if(self.updating){
                loadFunc()
                self.updating = false;
              }
            }
            else{
              self.updating = true;
            }
          });
        }
        else{
            element.style.display = "none";
            $(window).off("scroll.ko.scrollHandler")
            self.updating = false
        }
      }
     }
    
    0 讨论(0)
  • 2020-12-31 01:26

    I thought I would share some other scrollers I have found...

    https://github.com/thinkloop/knockout-js-progressive-filter

    https://github.com/thinkloop/knockout-js-infinite-scroll

    0 讨论(0)
提交回复
热议问题