【问题标题】:Backbone.js backed list not being refreshed by jQuery mobile (listview(‘refresh’))jQuery mobile 未刷新 Backbone.js 支持的列表 (listview('refresh'))
【发布时间】:2011-11-16 13:37:24
【问题描述】:

我正在尝试将排序选项添加到由主干.js 集合支持的 JQM 列表。我能够对集合进行排序(通过集合视图)并重新呈现列表,但 JQM 没有刷新列表。

我一直在搜索,发现了几个与我类似的问题(刷新 JQM 列表视图的问题),但我无法让它工作。

我试过打电话给$(‘#list’).listview(‘refresh’)$(‘#list-page’).page() 等都无济于事。我怀疑也许我在错误的地方调用了 refresh 方法(太早了),但我不确定我应该把它放在哪里(我刚从骨干开始)。

这是标记和 js。

HTML:

<div data-role="page" id="Main">
<div data-role="header"><h1>Main Page</h1></div>
<div data-role="content">   
        <ul data-role="listview">
            <li><a href="#Page1">Page 1</a></li>
        </ul> 
</div>
<div data-role="footer"><h4>Footer</h4></div>
</div>

<div data-role="page" id="Page1">
  <div data-role="header">
  <a href="#Main" data-role="back" data-icon="back">Back</a>
  <h1>Items</h1><a href="#dvItemSort" >Sort</a></div>
  <div data-role="content">
    <div id="dvTest">
        <ul id="ItemList" data-role="listview"  data-filter="true"></ul>
    </div>
  </div><div  data-role="footer"><h4>Footer</h4></div></div>

  <div data-role="page" id="dvItemSort">
  <div data-role="header"><h4>Sort</h4></div>
      <a href="#Page1" type="button" 
       name="btnSortByID" id="btnSortByID">ID</a>
      <a href="#Page1" type="button" 
       name="btnSortByName" id="btnSortByName">Name </a>
  </div>

Javascript:

  $(function () {

    window.Item = Backbone.Model.extend({
    ID: null,
    Name: null
});

window.ItemList = Backbone.Collection.extend({
    model: Item
});

window.items = new ItemList;
window.ItemView = Backbone.View.extend({
    tagName: 'li',

    initialize: function () {
        this.model.bind('change', this.render, this);
    },

    render: function () {
        $(this.el).html('<a>' + this.model.get('Name') + '</a>');
        return this;
    }
});

window.ItemListView = Backbone.View.extend({

    el: $('body'),

    _ItemViews: {},

     events: {
        "click #btnSortByID": "sortByID",
        "click #btnSortByName": "sortByName"
    },

    initialize: function () {
        items.bind('add', this.add, this);
        items.bind('reset', this.render, this);
    },

    render: function () {

        $('#ItemList').empty();

        _.each(items.models, function (item, idx) {
            $('#ItemList').append(this._ItemViews[item.get('ID')].render().el);
        }, this);
        
         $('#ItemList').listview('refresh'); //not working
        // $('#ItemList').listview(); 
        // $('#Page1').trigger('create');
         // $('#Page1').page(); //also doesn't work
    },


    add: function (item) {
        var view = new ItemView({ model: item });
        this._ItemViews[item.get('ID')] = view;
        this.$('#ItemList').append(view.render().el);

    },

    sortByName: function () {
        items.comparator = function (item) { return item.get('Name'); };
        items.sort();
    },

    sortByID: function () {
    
        items.comparator = function (item) { return item.get('ID'); };
        items.sort();
    }
});

window.itemListView = new ItemListView;

window.AppView = Backbone.View.extend({ 

    el: $('body'),

    initialize: function () {

        items.add([{ID: 1, Name: 'Foo 1'}, {ID:2, Name: 'Bar 2'}]);

    },
});

window.App = new AppView; 

});

编辑:我意识到我发布的第一行 html 标记没有显示在我的帖子中,所以我将其推下一行。

编辑 2: 这是代码 http://jsfiddle.net/8vtyr/2/ 的 jsfiddle 的链接

编辑 3 查看生成的标记,JQM 似乎将一些类添加到列表项中。我尝试使用标志手动添加它们,以确定列表是否由于排序而被重新渲染,然后列表正确显示。

但是,除了有点丑陋的解决方案之外,更重要的是,我在“项目”视图上的主干事件不再触发(在我发布的代码示例中,我没有放置事件的代码,因为我试图保留尽可能相关)。

EDIT 4 我通过清除我的视图缓存并重新创建它们来让它工作。我在下面发布了我的答案。

编辑 5 我用我认为更好的答案更新了我的答案。

【问题讨论】:

    标签: javascript jquery listview jquery-mobile backbone.js


    【解决方案1】:

    我有幸解决了这个问题,但原因对我来说仍然是模糊的。

    基本上,在我的元素建立html() 之后,在渲染视图的顶部,我调用listview()。然后,我可能会添加到列表中的任何其他项目调用listview('refresh')

    【讨论】:

    • 我也不确定为什么重新初始化 listview 有帮助,但我认为我最终得到的解决方案更有利,因为我没有重新渲染元素(在我的场景中我想只需对列表进行排序)。
    【解决方案2】:

    我不确定这是否应该是它自己的答案(我确实浏览了常见问题解答),所以现在我只是更新我之前的答案。

    我现在找到了一种使用缓存视图对列表进行排序的更好方法。本质上,诀窍是对集合进行排序,从 DOM 中分离元素,然后重新附加它们。 所以

    现在的代码是

     $list = $('#ItemList')
    
     $('li', $list ).detach();
     var frag = document.createDocumentFragment();
     var view;
        _.each(item.models, function (mdl) {
        view = this._ItemViews[item.get('ID')];
            frag.appendChild(view.el);
        },this);
    
       $list.append(frag);
    

    老答案

    我解决了这个问题。我正在检查渲染的元素,我注意到当元素“重新渲染”(在排序之后)时,它们丢失了事件处理程序(我在 firebug 中检查了)。所以我决定清除我的视图缓存并重新创建它们。这似乎可以解决问题,尽管我不确定究竟是为什么。

    代码:

    代替:

      $('#ItemList').empty();
        _.each(items.models, function (item, idx) {
            $('#ItemList').append(this._ItemViews[item.get('ID')].render().el);
        }, this);
         $('#ItemList').listview('refresh'); //not working
    

    我清除视图缓存并重新创建视图。

      $('#ItemList').empty();
            this._ItemViews = {};
            _.each(items.models, function (item, idx) {
                var view = new ItemView({ model: item  });
                this._ItemViews[item.get('ID')] = view;
                this.$('#ItemList').append(view.render().el)           
            }, this);
            $('#ItemList').listview('refresh'); //works now
    

    我认为如果我不需要重新生成缓存可能会更好,但至少这是一个可行的解决方案,如果我没有得到更好的答案,那么我会接受这个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-11
      • 2013-11-16
      • 2013-08-01
      • 2012-07-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多