【问题标题】:Backbone.view listenTo collections remove eventBackbone.view listenTo 集合删除事件
【发布时间】:2014-06-11 00:47:47
【问题描述】:

我正在努力正确地监听集合上的删除事件以重新渲染视图。

我的观点是这样的:

define(function(require) {
    var templ     = require('text!./../../templates/delete-deal-templ.html'),
        utils     = require('utils'),
        dealName  = '' ;


    return Backbone.View.extend({

        events: { 
             'click #delete-deal-btn' : 'deleteDealHandler',
        },

        template: _.template(templ),

        initialize: function() {
            this.listenTo(this.collection, 'remove', this.render);
        },

        render: function() {
            $(this.el).html(this.template({deals: this.collection}));
            ...
            return this;
        },

        deleteDealHandler: function(e) {
            e.preventDefault();
            ...
        }

    });
}); 

并像这样使用集合正确实例化:

DealEngine.getDeleteDealView = function() {
    require(['models/deal-model','views/delete-deal-view'], function(DealModel, DeleteDealView) {
        var DealCollection = Backbone.Collection.extend({
                model: DealModel,
                url: '/alldealsofbusiness/' + DealEngine.businessID
            }),
            dealCollection = new DealCollection(),   
            promise = dealCollection.fetch();
        promise.done(function(collection) {
            new DeleteDealView({collection: collection}).render();
            DealEngine.router.navigate('deletedeal');
            window.scrollTo(0, DealEngine.top_pos);
        }); 
        promise.fail(function() {
            var utils = require('utils');
            utils.growl('Your deals', 'could not be retrieved from our cloud, please try again!', 'error');
        });
    });
};

模板:

<div id="view-header" class="align-center">
    <h2>Delete a Deal</h2>
    <h5>Please note: Deals are automatically deleted after they have expired</h5>
</div>
<div class="row">
    <div class="col-xs-1 col-md-2"></div>
    <div class="col-xs-10 col-md-8">
        <div class="form-style" >
            <div id="select-deal" class="form-group dropdown">
                <a id="deal-select" class="btn btn-outline-inverse btn-lg dropdown-toggle" data-toggle="dropdown" role="button">
                    Select Deal
                    <span class="caret"></span>
                </a>
                <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
                    <% _.each(deals, function(deal) { %>
                        <li><a class="deal-option"><%= deal.deal.name %></a></li>
                    <% }); %>
                </ul>
            </div>
            <div class="col-xs-12 col-md-12">
                <div class="row align-center">
                    <div class="form-group">
                        <button id="delete-deal-btn" type="button" class="btn btn-outline-inverse btn-lg">Delete</button>
                    </div> 
                </div>
            </div>
        </div>
    </div>
    <div class="col-xs-1 col-md-2"></div>
</div>

this.collection 对象有正确的数据,this.render 是一个函数,但是视图初始化方法抛出

Uncaught TypeError: undefined is not a function

显然,我做错了什么,如果有人能对此有所了解,我将不胜感激。

【问题讨论】:

    标签: backbone.js


    【解决方案1】:

    我注意到的一件事是,您设置的变量等于我认为是异步的 require 调用。因此,即使尚未设置该变量,javascript 也会继续处理.. 您可能想尝试以下操作:

        var templ = require('text!./../../templates/delete-deal-templ.html', function(templ){
    //process logic in here
    });
    

    或者你可以在模块的define调用中将变量定义为依赖项。

    我已经把它改写成类似的东西,这对我有用(你必须修改它以符合你想要做的事情)。请注意,当您从模型中获取属性时,您希望使用 deal.get('name') 而不是 deal.name(当然,除非该属性直接设置在对象上)。

        <script type="text/template" id="testTemplate">
            <div id="view-header" class="align-center">
                <h2>Delete a Deal</h2>
                <h5>Please note: Deals are automatically deleted after they have expired</h5>
            </div>
            <div class="row">
                <div class="col-xs-1 col-md-2"></div>
                <div class="col-xs-10 col-md-8">
                    <div class="form-style">
                        <div id="select-deal" class="form-group dropdown">
                            <a id="deal-select" class="btn btn-outline-inverse btn-lg dropdown-toggle"
                               data-toggle="dropdown" role="button">
                                Select Deal
                                <span class="caret"></span>
                            </a>
                            <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
                                <% deals.each(function(deal) { %>
                                <li><a class="deal-option"><%= deal.get('name') %></a></li>
                                <% }); %>
                            </ul>
                        </div>
                        <div class="col-xs-12 col-md-12">
                            <div class="row align-center">
                                <div class="form-group">
                                    <button id="delete-deal-btn" type="button" class="btn btn-outline-inverse btn-lg">
                                        Delete
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="col-xs-1 col-md-2"></div>
            </div>
        </script>
    
        <script type="text/javascript">
            (function (_, Backbone, $) {
    $(document).ready(function () {
                var templateHtml = $('script#testTemplate').html();
                var templ = _.template(templateHtml);
    
                var view = Backbone.View.extend({
                    template: templ,
                    render: function () {
                        this.$el.html(this.template({deals: this.collection}));
                        return this;
                    },
                    initialize: function () {
                        this.collection.on('remove', this.render, this);
                    }
                });
    
                var testModel = Backbone.Model.extend({
                    defaults: {
                        name: 'test2'
                    }
                });
    
                var dealCollection = new Backbone.Collection();
                dealCollection.add(new testModel());
    
                dealCollection.add(new testModel());
    
                var deleteDealView = new view({
                    collection: dealCollection
                });
    
                var html = deleteDealView.render().$el.html();
                $('#test').append(html);
    });
            })(_, Backbone, jQuery);
        </script>
    

    顺便说一句,我会研究 Marionette,它可以为您处理大部分样板渲染逻辑。 https://github.com/marionettejs/backbone.marionette/tree/master/docs

    【讨论】:

    • 感谢您的建议,是的,我正在遍历模板中的集合。
    • 如果我注释掉 this.listenTo ...视图被正确实例化。
    • 你试过this.collection.on('remove', this, this.render);
    • 是的,我确实导致了相同的 TypeError。
    • 好的更新了答案,实际上没有相同的设置,我无法弄清楚究竟是什么导致了这个问题,但我对代码进行了一些修改,应该为您指明正确的方向。
    【解决方案2】:

    好吧,我的问题的根源是将服务器响应传递给视图而不是集合。 这是正确的代码sn-p:

    var DealCollection = Backbone.Collection.extend({
                model: DealModel,
                url: '/alldealsofbusiness/' + DealEngine.businessID
            }),
            dealCollection = new DealCollection(),   
            promise = dealCollection.fetch();
        promise.done(function() {
            new DeleteDealView({collection: dealCollection}).render();
            DealEngine.router.navigate('deletedeal');
            window.scrollTo(0, DealEngine.top_pos);
        });
    

    【讨论】:

      猜你喜欢
      • 2015-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多