【问题标题】:Set an Active property to only 1 model in a Backbone Collection at any time随时将 Active 属性设置为 Backbone 集合中的 1 个模型
【发布时间】:2015-01-19 21:07:26
【问题描述】:

我有一系列 Backbone 模型。我想将模型属性设置为“活动”,但要确保一次只能活动 1 个模型。我无法让它工作,正在寻找一些指导。

这是我的代码:http://jsfiddle.net/doen1mm9/

这是我的 JavaScript 和模板。

JS:

var data = [
    {
        "color": "blue",
        "name": "Johnny"
    },
    {
        "color": "green",
        "name": "Melissa"
    },
    {
        "color": "yellow",
        "name": "Bill"
    }
];

var TheModel = Backbone.Model.extend({
});

var TheCollection = Backbone.Collection.extend({
    model: TheModel,

    initialize: function() {
        this.on('change:isActive', this.ensureSingleActive, this);
    },

    ensureSingleActive: function(current) {
        var previous = this.findWhere({isActive: true});

        if (previous !== undefined) {
            previous.set('isActive', false);   
        }

        current.set('isActive', true);
    }
});

var ListView = Backbone.View.extend({
    el: '.js-container',

    tagName: 'ul',

    render: function() {
        this.collection.each(function(item) {
            var listItemView = new ListItemView({model: item});
            this.$el.append(listItemView.el);
        }, this);
    } 
});

var ListItemView = Backbone.View.extend({

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

    tagName: 'li',

    template: _.template( $('#item-template').html() ),

    render: function() {
        var temp = this.template({model: this.model.toJSON()});

        this.$el.html( temp );
    },

    events: {
        'click': 'toggleActive'   
    },

    toggleActive: function(e) {
        this.model.set('isActive');
        console.log(this.model.toJSON());
    }
});

var theCollection = new TheCollection(data);

var listView = new ListView({collection: theCollection});
listView.render();

模板:

<div class="js-container"></div>

<script type="text/template" id="item-template">
    <span <% if (model.isActive === true) { %> class="active" <% } %>>
        <%- model.name %>
    </span>
</script>

【问题讨论】:

    标签: javascript jquery backbone.js


    【解决方案1】:

    试试这个http://jsfiddle.net/ManikandanK/c477rone/1/ 您需要纠正两件事。

    ensureSingleActive: function(current) {
        if(current.get('isActive') ) {
    
            var previous=   _.find(this.models, function(model) {
                return model != current && model.get('isActive') 
            });
    
        if (previous) {
            previous.set('isActive', false);   
        } 
    }
    }
    

    当你在这个函数中时,当前模型值已经设置好了。所以你不需要再次设置值。您错过了将值传递给设置函数。

    this.model.set('isActive', true);
    

    【讨论】:

      【解决方案2】:

      要扩展其他答案,您可以回避事件并直接在您的集合上调用一个方法。

      在你看来:

      activate: function() {
        this.model.collection.setActive(this.model)
      }
      

      然后在你的收藏中:

      setActive: function(model) {
        this.each( function(m) { m.set('selected', m === model) }
      }
      

      可读性强,性能稍差,但除非您处理大量集合,否则这无关紧要。

      【讨论】:

        【解决方案3】:

        您在这里缺少额外的参数:

        toggleActive: function(e) {
                this.model.set('isActive'); // this.model.set('isActive', true);
        

        即使你解决了这个问题,你得到的例子也不会工作,因为你会陷入无限循环。

        this.on('change:isActive', this.ensureSingleActive, this);
        

        'ensureSingleActive' 将在每次 isActive 更改时被调用,因此当您在其中为其他模型设置 isActive 时,它​​将被重复调用。

        我的建议是确保在您的 ListView 中一次只有一个处于活动状态。甚至从 ListItemView 触发自定义,并确保只选择一个。

        我希望他的帮助。

        【讨论】:

        • 我确实注意到我在一些尝试中遇到了无限循环。谢谢你的建议!我认为使用模型作为一种设置活动项目的方法是一个好主意,而不是在列表中搜索一个类,删除它,然后将该类添加到单击的项目中。
        • 好吧,一旦模型设置好了,它的数据就会发生变化,并根据你的代码呈现。对我来说,这样做似乎有点违反直觉。据我所知,您需要一个了解模型的组件以设置为活动状态,以及其他 ListItems 的集合......所以基于此,我建议使用 ListView。
        猜你喜欢
        • 2012-12-30
        • 1970-01-01
        • 2016-04-29
        • 1970-01-01
        • 2012-04-13
        • 1970-01-01
        • 2014-12-16
        • 2014-10-04
        • 2012-12-02
        相关资源
        最近更新 更多