gpt4 book ai didi

javascript - Backbone View 事件不会触发

转载 作者:行者123 更新时间:2023-11-29 21:42:04 25 4
gpt4 key购买 nike

我有一个简单的主干 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 上的所有事件都消失了。听起来很熟悉?

你有很多东西会在你的 View 上调用 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. 在 View 上调用remove 以在不再需要它们时处理它们。
  3. 不要尝试重复使用 View ,在需要时创建 View ,在不需要时删除
  4. 没有 View 引用其 el 之外的任何内容。

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

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

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com