【问题标题】:Backbone listen to custom collection?Backbone 监听自定义集合?
【发布时间】:2014-11-09 05:14:21
【问题描述】:
// build a collection of players with this team ID
this.collection = new PlayersCollection(App.data.players.where({team_id: this.model.id}));

当我这样做时,它会呈现 this.collection = App.data.players; 它与集合是新集合有关,我如何收听新集合?

通过木偶,我通过 collectionViews、compositeViews 和 itemViews 将一组玩家传递到一组团队中。

Teams collectionView > Team compositionView > Player itemView

在团队复合视图中,我将 this.collection 定义为与特定团队 ID 匹配的新 PlayersCollection。这渲染得很完美,但是添加一个新播放器我无法在不刷新页面的情况下重新渲染视图。

addPlayer: function(e) {
    e.preventDefault();

    var $newPlayer = this.$el.find('input.player_name');

    var Player = {
        player_name : $newPlayer.val(), 
        team_id     : this.model.id
    }

    App.data.players.create(Player);
    $newPlayer.val('');

},

这里是大部分代码。我正在尝试添加/创建一个新播放器并使用listenTo 更新视图,但由于这不是定义集合的传统方式,我似乎必须找到一种方法来绑定它?

Teams.js

var Marionette = require('backbone.marionette'),
    playerView = require('./player'),
    PlayersCollection = require('../../collections/players');

var teamView = Marionette.CompositeView.extend({
    events: {
        'submit #AddPlayer': 'addPlayer'
    },
    initialize: function() {
        // anytime something within this specific team changes, render
        this.listenTo(this.model, 'change', this.render);

        // build a collection of players with this team ID
        this.collection = new PlayersCollection(App.data.players.where({team_id: this.model.id}));

    },
    addPlayer: function(e) {
        e.preventDefault();

        var $newPlayer = this.$el.find('input.player_name');

        var Player = {
            player_name : $newPlayer.val(), 
            team_id     : this.model.id
        }

        App.data.players.create(Player);
        $newPlayer.val('');

    },
    itemView: playerView,
    appendHtml: function(collectionView, itemView){
        collectionView.$('.the-players').append(itemView.el);
    }
});

module.exports = CollectionView = Marionette.CollectionView.extend({
    initialize: function() {
        this.listenTo(this.collection, 'change', this.render);
    },
    itemView: teamView
});

Players.js

var Marionette = require('backbone.marionette');

module.exports = playerView = Marionette.ItemView.extend({
    className: 'players-wrap row',
    template: require('../../../templates/teams/player.hbs'),
    events: {
        'mouseenter .player-image': 'playerOn',
        'mouseleave .player-image': 'playerOff',
        'click .player-image': 'playerClicked',
        'keydown': 'on_keypress',
        'click .one-point': 'onePoint',
        'click .two-point': 'twoPoint',
        'click .three-point': 'threePoint'
    },
    initialize:function() {
        _.bindAll(this, 'on_keypress');
        $(document).bind('keydown', this.on_keypress);
        this.listenTo(this.model, 'change', this.render);
        this.$el.attr('data-player', this.model.get('player_name').replace(/\s+/g,"_").toLowerCase());
        window.play = this.model;
    },
    playerOn:function(e) {
        this.$el.addClass('hover');
        this.findPlayer(this.model.get('player_name'), 'add');      
    },
    playerOff:function() {
        this.$el.removeClass('hover');
        this.findPlayer(this.model.get('player_name'), 'remove');
    },
    playerClicked:function() {
        this.$el.toggleClass('hover-clicked');
        this.findPlayer(this.model.get('player_name'), 'toggle'); 
    },
    findPlayer:function(name, action) {
        var player = $('.data-wrap .player-data[data-player='+ name.replace(/\s+/g,"_").toLowerCase() +']');
        if(action === 'toggle') { player.toggleClass('show-confirmed-clicked') }
        if(action === 'add')    { player.addClass('show-player-data') }
        if(action === 'remove') { player.removeClass('show-player-data') }
    },
    onePoint:function(e) {
        var addStat = parseInt(this.model.get('points')) + 1;        
        this.model.set('points', addStat);
        this.model.save();
    },
    twoPoint:function(e) {
        var addStat = parseInt(this.model.get('points')) + 2;        
        this.model.set('points', addStat);
        this.model.save();
    },
    threePoint:function(e) {
        var addStat = parseInt(this.model.get('points')) + 3;        
        this.model.set('points', addStat);
        this.model.save();
    },
    on_keypress:function(e) {
        this.keyStat(e, 49, 'points', 1);   // 1 point
        this.keyStat(e, 50, 'points', 2);   // 2 points
        this.keyStat(e, 51, 'points', 3);   // 3 points
        this.keyStat(e, 82, 'rebounds', 1); // R rebounds
        this.keyStat(e, 83, 'steals', 1); // S steals
    },
    keyStat:function(e, keyVal, stat, number) {
        if(e.keyCode == keyVal && !e.ctrlKey) { 
            if(this.$el.hasClass('hover')) {
                var addStat = parseInt(this.model.get(stat)) + number;        
                this.model.set(stat, addStat);
                this.model.save();
            }
        }
    },
    templateHelpers:function(){
        return {
            name_format: this.model.get('player_name').replace(/\s+/g, '_').toLowerCase()
        }
    }
});

【问题讨论】:

    标签: javascript backbone.js marionette


    【解决方案1】:

    我找不到您将新模型添加到 CompositeView 集合的位置?我发现只有App.data.players.create(Player); 不是 CompositeView 的集合。

    如果App.data.players 是另一个Backbone.Collection,您需要与远程服务器保持同步,因此您使用create 将其持久化到服务器,然后像这样更改addPlayer:

    addPlayer: function(e) {
        e.preventDefault();
    
        var $newPlayer = this.$('input.player_name');
    
        var Player = {
            player_name : $newPlayer.val(), 
            team_id     : this.model.id
        }
    
        var newPlayer = App.data.players.create(Player);
        this.collection.add(newPlayer);
        $newPlayer.val('');
    
    }, 
    

    CompositeView 将捕获集合的“添加”事件并附加新的 itemView。 请尝试让我知道它是否有帮助。

    请注意:在查看您的代码后,我发现 Teams.js 中的 appendHtml 可以使用值为 .the-playersitemViewContainer 属性删除,这将提高渲染性能。

    【讨论】:

    • 是的,所以它是一个嵌套集合,然后我将玩家从团队对象中取出,并将玩家集合设为全局,这很可能是它不会触发的原因,因为它是全局的。我需要将它传递到视图中。你说得对,我需要弄清楚如何对复合视图做到这一点
    • 工作得很好,谢谢。我希望我能想到这一点,哈哈。感谢这里的好人。
    • 我很高兴它有帮助。
    • 我正在阅读有关itemViewContainer 的信息,它只是一个函数。我应该如何将它换成appendHtml
    • 实际上它是CompositeView 的一个属性,如果设置了它,它将指向将呈现集合模型的ItemViews 的容器。阅读更多here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    相关资源
    最近更新 更多