Backbone 视图事件在渲染不止一次时不起作用
Backbone views events not working when rendering more than once
我有一个问题,我无法很好地理解 Backbone 观看事件。
几周前,我 运行 进入了“multiple views events triggering”问题,因为我将我所有的视图元素附加到一个现有的并且从未抑制的 DOM 元素(我的 #page_content
页面架构,见下文),并且我没有手动清理视图和事件)。
因为我不想手动清理,不是因为懒惰而是因为我发现它容易出错,所以我最终找到了一个很好的解决方法,那就是永远不要附加我对现有 DOM 元素的看法。所以我只使用 tagName
和 className
来创建我的视图元素,然后我将其插入到现有的 DOM 元素中(通常在 #page_content
中,见下文)。如果 Backbone 移除事件侦听器,如果它们附加到的 DOM 元素被移除,并且如果它们的元素从 DOM 中移除,也会垃圾收集视图,我觉得这是一个非常干净和处理视图及其事件的简单方法。
所以...直到今天,它一直运行良好。在我的一个视图中,我调用了两次 render
函数。第一次调用 render
函数时,一切正常。事件按预期触发和捕获。但是,如果我第二次调用 render
函数,我的视图事件中的 none 将被触发。
这是我的视图模板:
<script type="text/template" id="chat_selection_template">
<div class="push_me_down side_pad_me">
<div id="schools_chat_container">
<h2>Chat par école:</h2>
<ul>
<% if (schools) { %>
<% for (var i=0; i<schools.length; i++) { %>
<li class="school">
<a href="/chat/school/<%= schools[i].id %>" class="mlb_text blue">
<%= schools[i].attributes.appellation_officielle_uai %>Rejoindre ce chat
<i class="fa fa-chevron-right"></i>
</a>
</li>
<% } %>
<% } else { %>
<li class="empty">Vous n'êtes assigné(e) à aucune école pour le moment. <a class="mlb_text blue" href="/select_lines">Sélectionner une école à laquelle emmener vos enfants en Pédibus</a>.</li>
<% } %>
</ul>
</div>
<div id="lines_chat_container">
<h2>Chat par ligne:</h2>
<ul>
<% if (lines) { %>
<% for (var i=0; i<lines.length; i++) { %>
<li class="line"><%= lines[i].attributes.start_point_name %> - <%= lines[i].attributes.schoolName %> <a href="/chat/line/<%= lines[i].id %>" class="btn btn-mlb">Rejoindre ce chat</a></li>
<% } %>
<% } else { %>
<li class="empty">Vous n'êtes inscrit(e) à aucune ligne pour le moment. <a class="mlb_text blue" href="/select_lines">Inscrire mon enfant à une ligne de Pédibus</a>.</li>
<% } %>
</ul>
</div>
</div>
</script>
这是 JS:
// Chat selection page View
MLB.ChatSelectionView = Parse.View.extend({
tagName: 'div',
className: 'chat_selection_container',
template: _.template($("#chat_selection_template", MLB.TEMPLATES).html()),
schools: false,
lines: false,
events : {
"click #select_school_link": "go_select_a_school",
},
initialize : function() {
var School = Parse.Object.extend("School");
var school_query = new Parse.Query(School);
var current_user = Parse.User.current();
var Line = Parse.Object.extend("Route");
var line_query = new Parse.Query(Line);
var self = this;
school_query.equalTo("parents", current_user);
school_query.find().then(
function(schools) {
if (schools.length > 0) {
self.schools = schools;
}
self.render();
},
function(error) {
MLB.log_to_parse("middle",'chat_selection', 'Failed to retrieve schools.');
self.render();
}
);
line_query.equalTo("contributors", current_user);
line_query.find().then(
function(lines) {
if (lines.length > 0) {
self.lines = lines;
}
self.render();
},
function(error) {
MLB.log_to_parse("middle",'chat_selection', 'Failed to retrieve lines.');
self.render();
}
);
},
go_select_a_school: function(event) {
event.preventDefault();
Parse.history.navigate("consult_lines", {trigger: true});
},
render : function(schools) {
this.$el.html( this.template({schools: this.schools, lines: this.lines}) );
MLB.CONTENT.html(this.$el);
},
});
这是我的应用 HTML 架构:
<html>
<head></head>
<body>
<div id="content-wrapper">
<header id="page_header">
<div class="wrapper">
<h1 class="logo">
<a href="/" id="header_homepage">PetitBus</a>
</h1>
<div id="header_login"></div>
</div>
</header>
<div id="fb-root"></div>
<div id="page_content"></div>
<!-- TEMPLATES -->
<div id="templates">
[Backbone templates code]
</div>
</body>
</html>
我想明白为什么第二次调用 render
函数会搞砸了。据我对所见背后发生的事情的有限理解,当发生这种情况时,第一个渲染中的所有 DOM 元素都将被删除,它们的事件监听器也是如此。但是随后插入了新的 DOM 元素,它们的事件侦听器也是如此……对吗?至少那是我所期待的,但似乎我错了。
非常欢迎对此有任何见解。在误入歧途之前,我想深入了解这里发生了什么。
非常感谢
添加 this.delegateEvents();
作为渲染函数的最后一行。
Backbone documentation: "By default, delegateEvents is called within
the View's constructor for you, so if you have a simple events hash,
all of your DOM events will always already be connected, and you will
never have to call this function yourself."
因此,如果您第二次渲染视图,您需要自己调用 delegateEvents,因为不会再次调用构造函数。
我有一个问题,我无法很好地理解 Backbone 观看事件。
几周前,我 运行 进入了“multiple views events triggering”问题,因为我将我所有的视图元素附加到一个现有的并且从未抑制的 DOM 元素(我的 #page_content
页面架构,见下文),并且我没有手动清理视图和事件)。
因为我不想手动清理,不是因为懒惰而是因为我发现它容易出错,所以我最终找到了一个很好的解决方法,那就是永远不要附加我对现有 DOM 元素的看法。所以我只使用 tagName
和 className
来创建我的视图元素,然后我将其插入到现有的 DOM 元素中(通常在 #page_content
中,见下文)。如果 Backbone 移除事件侦听器,如果它们附加到的 DOM 元素被移除,并且如果它们的元素从 DOM 中移除,也会垃圾收集视图,我觉得这是一个非常干净和处理视图及其事件的简单方法。
所以...直到今天,它一直运行良好。在我的一个视图中,我调用了两次 render
函数。第一次调用 render
函数时,一切正常。事件按预期触发和捕获。但是,如果我第二次调用 render
函数,我的视图事件中的 none 将被触发。
这是我的视图模板:
<script type="text/template" id="chat_selection_template">
<div class="push_me_down side_pad_me">
<div id="schools_chat_container">
<h2>Chat par école:</h2>
<ul>
<% if (schools) { %>
<% for (var i=0; i<schools.length; i++) { %>
<li class="school">
<a href="/chat/school/<%= schools[i].id %>" class="mlb_text blue">
<%= schools[i].attributes.appellation_officielle_uai %>Rejoindre ce chat
<i class="fa fa-chevron-right"></i>
</a>
</li>
<% } %>
<% } else { %>
<li class="empty">Vous n'êtes assigné(e) à aucune école pour le moment. <a class="mlb_text blue" href="/select_lines">Sélectionner une école à laquelle emmener vos enfants en Pédibus</a>.</li>
<% } %>
</ul>
</div>
<div id="lines_chat_container">
<h2>Chat par ligne:</h2>
<ul>
<% if (lines) { %>
<% for (var i=0; i<lines.length; i++) { %>
<li class="line"><%= lines[i].attributes.start_point_name %> - <%= lines[i].attributes.schoolName %> <a href="/chat/line/<%= lines[i].id %>" class="btn btn-mlb">Rejoindre ce chat</a></li>
<% } %>
<% } else { %>
<li class="empty">Vous n'êtes inscrit(e) à aucune ligne pour le moment. <a class="mlb_text blue" href="/select_lines">Inscrire mon enfant à une ligne de Pédibus</a>.</li>
<% } %>
</ul>
</div>
</div>
</script>
这是 JS:
// Chat selection page View
MLB.ChatSelectionView = Parse.View.extend({
tagName: 'div',
className: 'chat_selection_container',
template: _.template($("#chat_selection_template", MLB.TEMPLATES).html()),
schools: false,
lines: false,
events : {
"click #select_school_link": "go_select_a_school",
},
initialize : function() {
var School = Parse.Object.extend("School");
var school_query = new Parse.Query(School);
var current_user = Parse.User.current();
var Line = Parse.Object.extend("Route");
var line_query = new Parse.Query(Line);
var self = this;
school_query.equalTo("parents", current_user);
school_query.find().then(
function(schools) {
if (schools.length > 0) {
self.schools = schools;
}
self.render();
},
function(error) {
MLB.log_to_parse("middle",'chat_selection', 'Failed to retrieve schools.');
self.render();
}
);
line_query.equalTo("contributors", current_user);
line_query.find().then(
function(lines) {
if (lines.length > 0) {
self.lines = lines;
}
self.render();
},
function(error) {
MLB.log_to_parse("middle",'chat_selection', 'Failed to retrieve lines.');
self.render();
}
);
},
go_select_a_school: function(event) {
event.preventDefault();
Parse.history.navigate("consult_lines", {trigger: true});
},
render : function(schools) {
this.$el.html( this.template({schools: this.schools, lines: this.lines}) );
MLB.CONTENT.html(this.$el);
},
});
这是我的应用 HTML 架构:
<html>
<head></head>
<body>
<div id="content-wrapper">
<header id="page_header">
<div class="wrapper">
<h1 class="logo">
<a href="/" id="header_homepage">PetitBus</a>
</h1>
<div id="header_login"></div>
</div>
</header>
<div id="fb-root"></div>
<div id="page_content"></div>
<!-- TEMPLATES -->
<div id="templates">
[Backbone templates code]
</div>
</body>
</html>
我想明白为什么第二次调用 render
函数会搞砸了。据我对所见背后发生的事情的有限理解,当发生这种情况时,第一个渲染中的所有 DOM 元素都将被删除,它们的事件监听器也是如此。但是随后插入了新的 DOM 元素,它们的事件侦听器也是如此……对吗?至少那是我所期待的,但似乎我错了。
非常欢迎对此有任何见解。在误入歧途之前,我想深入了解这里发生了什么。
非常感谢
添加 this.delegateEvents();
作为渲染函数的最后一行。
Backbone documentation: "By default, delegateEvents is called within the View's constructor for you, so if you have a simple events hash, all of your DOM events will always already be connected, and you will never have to call this function yourself."
因此,如果您第二次渲染视图,您需要自己调用 delegateEvents,因为不会再次调用构造函数。