- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我对 backbone 还很陌生,我试图了解僵尸 View 的来龙去脉。
僵尸是,根据这个article :
When we bind objects together through events but we don’t bother unbinding them. As long as these objects are bound together, and there is a reference in our app code to at least one of them, they won’t be cleaned up or garbage collected. The resulting memory leaks are like the zombies of the movies – hiding in dark corners, waiting to jump out and eat us for lunch.
上面提到的文章建议创建一个对象来管理 View 之间的转换,然后实现一个关闭函数来删除和取消绑定(bind) View 。
也就是说,根据情况,从哪里调用关闭函数?
我在父 View 的初始化 block 中添加了一个属性来跟踪 subview 。这样我就可以在用新的替换它之前对其调用 .remove() 。这是好的做法还是有更好的方法?
我也不明白为什么要定义el
然后用
this.$el.html(this.template(this.model.attributes));
不允许我取消绑定(bind) View ,而它按预期的方式工作
$('#sportsManDetails').html(this.$el.html(this.template(this.model.attributes)));
至于示例,我刚刚创建了一个简单的应用程序,它显示运动员姓名列表,并在单击姓名时显示更多详细信息。
这是代码和工作 fiddle :
html
<script id="nameListTemplate" type="text/template">
<%= first %> <%= last %>
</script>
<script id="sportsManDetailsTemplate" type="text/template">
<ul>
<li><%= first %></li>
<li><%= last %></li>
<li><%= age %></li>
<li><%= sport %></li>
<li><%= category %></li>
</ul>
<button class="test">Test</button>
</script>
<div id="sportsMenName"></div>
<div id="sportsManDetails"></div>
JS
模型和集合
var app = app || {};
app.SportsManModel = Backbone.Model.extend({});
app.SportsMenCollection = Backbone.Collection.extend({
model: app.SportsManModel
});
名称 View
app.NameView = Backbone.View.extend({
tagName: 'li',
className: 'sportsMan',
template: _.template($('#nameListTemplate').html()),
initialize: function(){
this.sportsManDetailsView;
},
events: {
'click': 'showSportsManDetails'
},
showSportsManDetails: function(e){
if (typeof this.sportsManDetailsView !== 'undefined'){
this.sportsManDetailsView.remove();
}
this.sportsManDetailsView = new app.SportsManDetailsView({
model: this.model
})
},
render: function(){
this.$el.append(this.template(this.model.attributes));
return this;
}
});
名称 ListView
app.NameListView = Backbone.View.extend({
el: '#sportsMenName',
initialize: function(sportsMen){
this.collection = new app.SportsMenCollection(sportsMen);
this.render();
},
render: function(){
this.collection.each(function(sportsMen){
this.renderContact(sportsMen);
}, this);
},
renderContact: function(sportsMen){
var nameView = new app.NameView({
model: sportsMen
});
this.$el.append(nameView.render().el);
}
});
SportsManDetailsView
app.SportsManDetailsView = Backbone.View.extend({
// doesn't work if I use el in conjunction with
// this.$el.html(this.template(this.model.attributes));
// el: '#sportsManDetails',
template: _.template($('#sportsManDetailsTemplate').html()),
initialize: function(){
this.render();
},
events: {
'click .test': 'test'
},
test: function(){
alert('test');
},
render: function(){
// that does not work
//this.$el.html(this.template(this.model.attributes));
// is this good practice?
$('#sportsManDetails').html(this.$el.html(this.template(this.model.attributes)));
}
});
app.js
var sportsMen = [
{first: 'Quentin', last: 'Tarant', age: '34', sport: 'bike', category: '- 90kg'},
{first: 'Aymeric', last: 'McArthur', age: '54', sport: 'jetski', category: '200HP'},
{first: 'Peter', last: 'TheFat', age: '45', sport: 'curling', category: 'dunno'},
{first: 'Charles', last: 'Martel', age: '21', sport: 'Moto', category: 'MX 250cc'},
];
$(function(){
new app.NameListView(sportsMen);
});
最佳答案
正如您所发现的,Backbone 认为自己更像是一个库 而不是一个框架 - 它给开发人员留下了很多问题和设计模式。
术语“僵尸 View ”用于指定在您认为它们已死时仍然绑定(bind)到某物(因此还活着)的 View 。通常有来自 model.on 调用或类似的对 View 的剩余引用。基本上是一种特定形式的内存泄漏。
要管理 View 的生命周期,您可以使用父 View ,但通常的做法是从路由器执行此操作。路由器用于删除旧 View 并根据路由事件实例化新 View 。以下是我通常如何完成此操作的片段:
render: function(){
this.mainView && this.mainView.remove(); // if there is already a view, remove it
this.mainView = new SomeOtherKindOfViewDeterminedBySomeEvent(); // instantiate the new view
this.mainView.render();
this.mainView.$el.appendTo( '#main-content' ); // append it
}
一些注意事项:
remove
,您的应用程序将容易受到内存泄漏的影响。这是因为 View 的事件和属性仍然存在于后台。例如,如果你删除上面例子的第一行,我将失去对以前的 this.mainView
的引用,但它的事件仍在使用内存。随着时间的推移,这会对您的应用产生影响。请注意,我在最后一行使用了 appendTo
。在 View 上调用 remove
时,它的整个元素及其事件都会被移除。如果我只是这样做:
this.mainView = new SomeOtherKindOfViewDeterminedBySomeEvent({ el: '#main-content' })
然后在我调用 this.mainView
上的 remove
之后,#main-content
将从 DOM 中删除,所以我不能不再使用该选择器。通过附加它,我将 #main-content
保留为占位符,因此我可以继续向其附加 View 。 这就是您在尝试解除绑定(bind) SportsManDetailsView
然后再次渲染时看到的内容。
至于你的问题,这个:
$('#sportsManDetails').html(this.$el.html(this.template(this.model.attributes)));
不是好的做法。首先是您使用了全局 jQuery 对象,它破坏了 Backbone 的封装 View 方法。其次,从以前的 View 来看,事件在 DOM 中仍然处于事件状态,从而导致内存泄漏。单击“测试”按钮时可以看到这一点 - 每次实例化 SportsManDetailsView
时都会触发处理函数(第二次,警报消息将显示两次,然后显示三次,依此类推。 )
您应该依靠父 View 或路由器来处理此类交互。那,或者让你的 SportsManDetailsView
绑定(bind)到 #sportsManDetails
元素,永远不要删除它。然后,当您的 NameView
中发生点击事件时,让它的模型触发器触发一个事件。然后您的 SportsManDetailsView
可以监听相应集合中的事件并相应地重新呈现自己。 拥抱 Backbone 的事件!JavaScript 是一种事件驱动的语言,永远不要忘记您的大炮中有这些事件。
我已经更新了你的JSFiddle来展示我所说的一些内容。
关于javascript - Backbone 僵尸观点和良好实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25916009/
Closed. This question is opinion-based。它当前不接受答案。
我有一个项目需要在工作和在家中使用两台不同的计算机进行。 我需要能够在两台计算机上都处理代码,所以问题有两个。 共享代码 共享工作空间。 用svn 1很简单;但是我感到很讨厌将损坏的代码提交给svn,
我正在尝试在 Eclipse 中实现 coreNLP 情绪分析器。得到错误: Unable to resolve "edu/stanford/nlp/models/lexparser/englishP
我有一个输入框: 如果我在输入字段中输入 .75 ,则应在 .75 之前自动添加 0 ,使其变为 0.75 此外,如果我输入 1.3 那么它应该变成 1.30 我已经尝试过: echo "
我有一个带有以下行的父组件 根据上下文,它呈现路由器配置中定义的两个组件之一 path: 'parent', component: Parent, children: [ {
我安装了最新的 angular-ui-select (v0.12) 和 angular v1.2.27。我的页面无法加载。我得到: expected expression, got . (a poin
我是一名优秀的程序员,十分优秀!