javascript - 主干 View 事件不会触发

标签 javascript jquery backbone.js backbone-views backbone-events

我有一个简单的主干 View 如下:

/**
 * Renders a form view for an event object.
 */
APP.EventFormView = Backbone.View.extend({
    tagName: 'form',

    events: {
        'keydown': 'keyPressed',
        'focus input': 'inputChanged',
        'change select': 'selectChanged',
        'change textarea': 'textareaChanged'
    },

    initialize: function() {
        this.template = _.template($('#newevent-form').html());
        this.listenTo(this.model, 'change', this.render);
        this.listenTo(APP.eventTypes, 'update', this.render);
        this.listenTo(APP.selectedEvent, 'update', this.render);
    },

    render: function() {
        var modelJSON = this.model.toJSON();
        if ('id' in modelJSON && modelJSON.id !== "") {
            this.loadForm();
        } else if (!('id' in modelJSON) || modelJSON.id === "") {
            this.loadForm();
        } else {
            this.$el.html('');
        }
        return this;
    },

    loadForm: function() {
        var templateData = $.extend(this.model.toJSON(),
            {"event_types":APP.eventTypes.toJSON()});
        this.$el.html('');
        this.$el.html(this.template($.extend(this.model.toJSON(),
                {event_types: APP.eventTypes.toJSON()})));
        $('.ev-main-container').html('').html(this.el);
    },

    inputChanged: function(e) {
        console.log('inputChanged');
    },

    selectChanged: function(e) {
        console.log('selectChanged');
    },

    textareaChanged: function(e) {
        console.log('textareaChanged');
    },

    keyPressed: function(e) {
        console.log('key pressed');
    }
});

我在 document.ready 下按如下方式初始化此 View :

// Initialize the form view
APP.selectedEvent = APP.selectedEvent || new APP.Event();
APP.eventFormView = new APP.EventFormView({model: APP.selectedEvent});
APP.eventFormView.render();

但是由于某种原因,我定义的事件都没有触发,我在这里做错了什么?

更新:

好吧,如果我从 loadForm< 中删除 $('.ev-main-container').html('').html(this.el); ,我就忘了 方法并按如下方式初始化 View ,它可以工作:

APP.eventFormView = new APP.EventFormView({
    model: APP.selectedEvent,
    el: $('.ev-main-container'),
});

我能够解决这个问题,但我仍然不明白为什么会发生这种情况,任何人都可以解释一下发生了什么以及它是如何工作的。

最佳答案

jQuery 的 html函数有一个许多人似乎忘记的副作用,来自 fine manual :

jQuery removes other constructs such as data and event handlers from child elements before replacing those elements with the new content.

考虑一下当你做这样的事情时这意味着什么:

container.html(view.el);
container.html(view.el);

第一次之后一切都会好起来的container.html()称呼。但第二个将在添加新内容之前“从子元素中删除...事件处理程序”(例如 view.el )。所以在第二个container.html()之后调用电话,所有事件都在view.el消失了。听起来很熟悉吗?

你有很多东西会调用render根据您的观点和 render最终会这样做:

$('.ev-main-container').html('').html(this.el);

您的事件将在第二次被调用时悄然消失,但 HTML 看起来会很好。

考虑这个简化的示例 ( http://jsfiddle.net/ambiguous/otnyv93e/ ):

var V = Backbone.View.extend({
    tagName: 'form',
    events: {
        'click button': 'clicked'
    },
    initialize: function() {
        this.template = _.template($('#t').html());
    },
    render: function() {
        this.$el.html('');
        this.$el.html(this.template());
        $('.ev-main-container').html('').html(this.el);
        return this;
    },
    clicked: function() {
        console.log('clicked');
    }
});
var v = new V;
v.render();
$('#re-render').click(function() {
    v.render();
    console.log('Re-rendered');
});

然后你就会清楚地看到你的问题。

如果您将 View 设为 el .ev-main-container那么你将使用html()更改 el 的内容而不是更改包含 el 的元素的内容。一旦你完全在 el 内工作您不再意外地重复使用某个元素,也不再意外地从该元素中删除事件绑定(bind)。

我的防止 Backbone 事件问题的经验法则:

  1. 永远不要将 View 附加到现有的 DOM 节点,始终让 View 创建并拥有自己的 el让调用者输入 el在容器中。
  2. 调用 remove在不再需要它们时处理它们的 View 。
  3. 不要尝试重复使用 View ,在需要时创建它们,remove当您不需要它们时就使用它们。
  4. 没有 View 引用其 el 之外的任何内容.

也有异常(exception)(当然),这种方法并不能解决所有问题,但它是一个很好的起点,可以避免大多数常见问题。

关于javascript - 主干 View 事件不会触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32411395/

相关文章:

javascript - 没有定义 url 的主干验证方法

javascript - Backbone.js View 在其创建期间的生命周期

javascript - 从模型获取属性并在模板中显示它 - Backbone

jQuery CSS 背景变化

javascript - 启动表排序程序时遇到问题

javascript - 使用 Flexslider 进行哈希 URL 导航

javascript - 如何从 Style 属性中删除属性?

javascript - 动态添加/删除元素

jquery - 需要绘制/动画一个小方形背景图像,然后在 x 和 y 上重复它

javascript - 将 JSON 对象项添加到具有相同类的 DIV