理解Backbone.js中的排序和比较器

xa9qqrwz  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(175)

我试图理解Backbone.js中的排序和比较器。我在网上看到了很多答案,但我一直无法让他们中的任何一个工作。使用经典的“ToDo”应用程序的jsfiddle:https://jsfiddle.net/quovadimus/9z3wnoh2/2/我试过修改第34行:
第一个月

comparator:  function(model) {
       return -model.get('order');
   }

字符串
或者甚至简单地说:
comparator: 'title
我在第一个待办事项的标题中输入“zzz”,在下一个待办事项中输入“aaa”。我希望我的任何一个修改都能颠倒todos的列表顺序。但每次都按原来的顺序显示。我错过了什么?谢谢你

mklgxw1f

mklgxw1f1#

您正确理解了comparator的工作原理。但是,调整集合的顺序只是故事的一半。视图(在本例中为AppView)仍然可以自由地以任何顺序显示集合中的模型。在您所链接的fiddle中,确定表示顺序的代码行如下:

var AppView = Backbone.View.extend({
        // ...
        initialize: function() {
            // ...
            this.listenTo(Todos, "add", this.addOne);
            this.listenTo(Todos, "reset", this.addAll);
            // ...
        },
        // ...
        addOne: function(todo) {
            var view = new TodoView({model: todo});
            this.$("#todo-list").append(view.render().el);
        },
        addAll: function() {
            Todos.each(this.addOne, this);
        },
        // ...
    });

字符串
基本上,这段代码是这样写的:
1.在 normal 情况下(add事件,addOne方法),将最新的todo放在列表的底部。
1.在例外情况下(reset事件,addAll方法),按照它们在集合中出现的顺序放置todos。
reset事件的例外情况永远不会发生在你的fiddle中,即使你用localStorage中已经存在的一些todos刷新应用程序,也不会发生,因为fetch方法调用的是set而不是reset
要解决这个问题,请构建视图,使其始终遵循集合的顺序。这说起来容易做起来难出于这个原因,我建议使用专用的库,例如backbone-fractalMarionette,这两个库都为此提供了CollectionView。但是,为了便于学习,这里提供了一种在视图中镜像集合顺序的基本方法。
开始之前,请停止从外部渲染视图。你会在互联网上看到像view.render().el这样的代码行,因为它是很好的示例代码,但你不应该在生产环境中这样做。视图的呈现是内部事务,是视图自己关心的问题(除非呈现的开销非常大,您应该尽量避免这种情况,并且视图本身无法确定是否是正确的时机)。在大多数情况下,视图应该在其initialize方法中呈现一次,然后在其模型触发'change'事件时再次呈现。换句话说,将这一行添加到TodoView.initialize

this.render();


现在这可能看起来并不重要,但请相信我的话,如果每个单独的视图只需要跟踪何时呈现自己,那么它将极大地简化问题。
接下来,您需要将 * 创建 * 子视图(TodoView的示例)与 * 放置 * 这些子视图分开。* 创建 * 子视图应该在两种情况下发生:
1.当初始化父视图(AppView)时,对于此时恰好已经在集合中的每个模型。
1.每次在此之后,当一个新模型被添加到集合中时,即在add事件上。

  • 放置 * 子视图也应该在两种情况下发生,但它们并不完全相同:

1.初始化父视图时,对于当时恰好已经在集合中的每个模型。
1.每次在此之后,当集合获得新模型或更改顺序时,即在update事件上。
由于创建和放置子视图需要在时间上分开,因此您必须同时存储子视图。这也意味着当模型再次被删除时,您将需要更新存储。
您可以选择不同的存储方法,这反过来又会影响如何创建和放置子视图。下面,我将演示一种方法,该方法将子视图保存在一个对象中,该对象由相应模型的cid索引。请记住,这是示例代码;基本原则是正确的,但在实践中,把所有的细节都做好是很棘手的。使用像backbone-fracture这样的库可以保存你的麻烦。

var AppView = Backbone.View.extend({
        // ...
        initialize: function() {
            // ...
            this.resetSubviews().placeSubviews().listenTo(Todos, {
                add: this.addSubview,
                remove: this.forgetSubview,
                update: this.placeSubviews,
                reset: this.resetSubviews,
            });
            // ...
        },
        // ...
        addSubview: function(todo) {
            this.subviews[todo.cid] = new TodoView({model: todo});
        },
        forgetSubview: function(todo) {
            delete this.subviews[todo.cid];
        },
        placeSubviews: function() {
            var model2el = _.compose(_.property('el'), _.propertyOf(this.subviews), _.property('cid'));
            var subviewEls = Todos.map(model2el);
            this.$('#todo-list').append(subviewEls);
            return this;
        },
        resetSubview: function() {
            this.subviews = {};
            Todos.each(this.addSubview, this);
            return this;
        },
        // ...
    });

相关问题