javascript - Backbone 收藏刷新所有元素

标签 javascript backbone.js jquery-ui-sortable

更新服务器上的所有模型后,我在刷新集合或更准确地说 Collection View 时遇到问题。这是我的场景:

  1. 我从服务器获取了一系列问题。每个问题都有一个位置属性,因此我可以操纵列表中的顺序并以适当的顺序将其保存回服务器。

  2. 我有每个列表项的 View 和具有更全局范围的 View ,该 View 生成每个列表项并更新集合。基本上,我使用的是 O'Reilly 书籍“Javascript Web 应用程序”中的示例,它与此处找到的著名的 Todo 带注释教程非常相似: http://documentcloud.github.com/backbone/docs/todos.html 因此,除了一些定制模型之外,结构几乎相同。一切正常。

  3. 但是,我在更新集合时遇到问题,因为我重新排序了 我的全局 View 中有一个方法,每当我在列表中拖动列表项时都会触发该方法。顺便说一句,它运行良好并更新服务器上项目的顺序,但我也希望能够更新列表中每个项目的数字。

    window.QuestionView = Backbone.View.extend({
    
    el: $("#content"),
    events : {
        'sortupdate ol#questions': 'sortStuff'
    },
    
    initialize: function(collection) {
        this.collection = new QuestionsList;
    
        _.bindAll(this, 'addOne', 'addAll', 'render', 'addNewItem', 'addItem');
        this.collection.bind('add', this.addNewItem);
        this.collection.bind('all', this.render);
        this.collection.bind('reset', this.addAll);
        this.collection.fetch({
            data: { quiz_id: $qid },
            processData:true
        });
    },
    
    render: function() {},
    
    sortStuff: function() {
    
        $this = this;
        $.ajax({
            url: "/hq/reorder/",
            type: "POST",
            data: $("#questions").sortable("serialize")+"&id="+$qid,
            dataType: 'json',
            success: function(data) {
    
            }
        });
    },
    
    addItem: function() {
        this.collection.add({title: 'New title goes here'});
        return false;
    },
    
    addNewItem: function(question) {
        var view = new ItemView({model: question, parent: this});
        var element = view.render().el;
        this.$("#questions").prepend(element);
        $that = this;
        $(view.render().el).addClass('new');
    },
    
    addOne: function(question) {
      var view = new ItemView({model: question, parent: this});
      this.$("#questions").prepend(view.render().el);
    },
    
    addAll: function() {
      this.collection.each(this.addOne);
      return false;
    }
    

    });

所以我的问题是..成功后我该怎么做:能够单独刷新每个小模型,以便将数字更新为正确的顺序?也许是 Collection 上的某种 _.each ?或者也许对整个集合进行某种全局 View 刷新?

还有我的 成功:函数(数据) 从服务器返回新订单作为列表(或 JSON 对象)。也许我可以重用此订单来为每个模型设置新值,而无需每次更改订单时在服务器上进行不必要的 fetch() 调用?

编辑:

我终于设法让它通过重置、清除 View 并重新获取新集合来工作。也许这不是最好的方法,因为需要使用 fetch() 对服务器进行额外的调用..

 sortStuff: function() {

        $this = this;
        $.ajax({
            url: "/hq/reorder/",
            type: "POST",
            data: $("#questions").sortable("serialize")+"&id="+$qid,
            dataType: 'json',
            success: function(data) {
                $this.rerender();
            }
        });


    },

    rerender: function() {

        this.collection.fetch({
            data: { quiz_id: $qid },
            processData:true
        });
        $("#questions").html("");
        this.collection.reset();
        this.addAll();
    },

最佳答案

我认为你的方法应该分为两个单独的步骤: 1)一方面你更新服务器上的数据 2) 另一方面,您更新集合客户端

所以,您在第 1 步上没问题,您说它有效。

对于步骤 2,您可以利用事件驱动编程。 逻辑是这样的:

  1. 您只需向集合中添加一个元素(collection.add(model) 会触发“add”事件)。
  2. 在集合中,您监听“add”事件。当您捕获它时,您将再次对集合进行排序(collection.sort 会触发“重置”事件)
  3. 在 ListView 中(在您的例子中为 QuestionView),您监听集合重置事件,一旦触发,您将重新渲染 View

示例代码:

1) QuestionView:删除了 addItem 并简化了 addNewItem(不得渲染)

 window.QuestionView = Backbone.View.extend({
 el: $("#content"),
 events : {
     'sortupdate ol#questions': 'sortStuff'
 },

 initialize: function(collection) {
     this.collection = new QuestionsList;
     _.bindAll(this, 'addOne', 'addAll', 'addNewItem');
     this.collection.bind('add', this.addNewItem);
     this.collection.bind('reset', this.addAll);
     this.collection.fetch({
     data: { quiz_id: $qid },
     processData:true
     });
 },

 render: function() {},

 sortStuff: function() {

     $this = this;
     $.ajax({
         url: "/hq/reorder/",
         type: "POST",
         data: $("#questions").sortable("serialize")+"&id="+$qid,
         dataType: 'json',
         success: function(data) {

         }
     });
 },

 //METHOD addItem REMOVED!!!


 addNewItem: function(question) {
     this.collection.add({title: 'New title goes here'}); //***IT FIRES AN ADD EVENT
     },

 addOne: function(question) {
   var view = new ItemView({model: question, parent: this});
   this.$("#questions").prepend(view.render().el);
 },

 addAll: function() {
   this.collection.each(this.addOne);
   return false;
 }

});

2)集合捕获添加事件并排序(触发“重置”事件) 您可以始终在 QuestionView 中处理它,您的初始化函数将变为。

 initialize: function(collection) {
     this.collection = new QuestionsList;
     _.bindAll(this, 'addOne', 'addAll', 'addNewItem');
     this.collection.bind('add', this.addNewItem);
     this.collection.bind('reset', this.addAll);
     this.collection.fetch({
     data: { quiz_id: $qid },
     processData:true
     });
     //ADD THIS*****
     this.collection.on('add', function(){
         this.collection.sort();
     });
 },

3)第三步已经完成,你只需重新渲染 View

最好的方法是对集合中的元素进行排序,定义一个新的“比较器”函数,该函数使用列表的“位置”属性

类似于(在 QuestionView 中)

this.collection.comparator: function(){
   return this.collection.get("position");
}

以便项目按位置排序客户端

**编辑** 修改初始化函数。使用fetch代替'sort',只要集合中每个元素的'position'属性不更新,这是没有用的。

 initialize: function(collection) {
     this.collection = new QuestionsList;
     _.bindAll(this, 'addOne', 'addAll', 'addNewItem');
     this.collection.bind('add', this.addNewItem);
     this.collection.bind('reset', this.addAll);
     this.collection.fetch({
     data: { quiz_id: $qid },
     processData:true
     });
     //ADD THIS*****
     this.collection.on('add', function(){
         this.collection.fetch();
     });

关于javascript - Backbone 收藏刷新所有元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9309893/

相关文章:

jquery - 为什么除 Chrome 之外的所有浏览器都无法编辑可排序 div 中的文本区域和文本输入字段?

javascript - 使用 Google Charts 传递数据

javascript - 如何解析javascript中的字符串语句?

javascript - 在 Angular 工厂的函数中设置变量

backbone.js - 保存主干模型时出错 : Uncaught Error: A "url" property or function must be specified

jquery - 如何在 JavaScript 中触发 jQuery-sortable 的 "update"事件?

javascript - 如何使用 javascript 在 sortable 中查找值的项目

javascript - 保存拖动元素的位置 - JavaScript

返回对象文字的 Javascript 语法问题

javascript - 如何在 Backbone.Marionette View 中最轻松地呈现 i18n 文本和模型属性(使用 Handlebars 模板)