多次渲染时,Backbone 视图事件不起作用
Posted
技术标签:
【中文标题】多次渲染时,Backbone 视图事件不起作用【英文标题】:Backbone views events not working when rendering more than once 【发布时间】:2015-05-30 19:47:05 【问题描述】:我有一个问题,我无法很好地理解 Backbone 视图事件。
几周前,我遇到了“multiple views events triggering”问题,因为我将所有视图元素附加到一个现有且从未抑制的 DOM 元素(我的页面架构中的#page_content
,见下文),而我没有t 手动清理视图和事件)。
因为我不想手动进行清理,不是因为懒惰,而是因为我发现它容易出错,所以我最终找到了一个很好的解决方法,即永远不要将我的视图附加到现有 DOM元素。所以我只使用tagName
和className
来创建我的视图元素,然后我将其插入到现有的DOM 元素中(通常是在#page_content
中,见下文)。由于 Backbone 会在它们附加到的 DOM 元素被删除时删除事件侦听器,并且如果它们的元素从 DOM 中删除,也会对 Views 进行垃圾收集,我发现这是一种处理 Views 及其事件的非常干净和简单的方法。
所以...直到今天它一直运行良好。在我的一个视图中,我调用了两次render
函数。第一次调用 render
函数时,一切正常。事件按预期触发和捕获。但是,如果我第二次调用render
函数,我的视图事件将不再被触发。
这是我的视图模板:
<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 元素,它们的事件侦听器也是如此……对吗?至少这是我所期待的,但似乎我错了。
非常欢迎对此的任何见解。我想深入了解这里发生的事情,然后再朝错误的方向前进。
非常感谢
【问题讨论】:
两次调用render是指代码中的两次调用。一个在school_query的回调中,另一个在lines_query的回调中? 感谢您的回复。是的,我的意思是这两个电话。我这样做,所以我可以更快地向用户输出一些东西,并在第二个回调的信息返回时完成视图。你觉得这里有什么问题吗? 【参考方案1】:添加this.delegateEvents();
作为渲染函数的最后一行。
Backbone 文档:“默认情况下,delegateEvents 在 视图的构造函数,所以如果你有一个简单的事件哈希, 您的所有 DOM 事件将始终已连接,并且您将 永远不必自己调用这个函数。”
因此,如果您再次渲染视图,则需要自己调用 delegateEvents,因为不会再次调用构造函数。
【讨论】:
罗杰。我知道delegateEvents
,但不太了解它在做什么。有了这个案例和你的解释,现在就一清二楚了。谢谢!以上是关于多次渲染时,Backbone 视图事件不起作用的主要内容,如果未能解决你的问题,请参考以下文章
Backbone.js — 匿名视图实例中的集合在获取时多次请求
当尝试从带有点击事件的视图滚动时,滚动在 NestedScrollView 中不起作用