我正在使用骨干,把手和jquery-mobile开发单页应用。无论我如何尝试清理它们,我都面临着导致DOM节点不断上升的问题。
为了更好地展示这个问题,我创建了一个结构与我的应用程序完全相同的简单程序,并且遇到了同样的问题。整个应用程序只有4个文件:
的index.html:
<!doctype html>
<html>
<head>
<script id="home-tpl" type="text/x-handlebars-template">
{{> header}}
<div data-role="content">
<a id="page1Link" href="#page1" data-role="button">goto Page1</a>
</div>
{{> footer}}
</script>
<script id="page1-tpl" type="text/x-handlebars-template">
{{> header}}
<div data-role="content">
<h1>Hello, am I leaking?</h1>
</div>
{{> footer}}
</script>
<script id="header-partial" type="text/x-handlebars-template">
<div id="header" data-id="myHeader" data-role="header" data-position="fixed" data-theme="a">
<a href="#home" data-icon="arrow-l">Back</a>
<h1>{{pageTitle}}</h1>
</div>
</script>
<script id="footer-partial" type="text/x-handlebars-template">
<div id="footer" data-id="myFooter" data-role="footer" data-position="fixed" data-theme="a">
<h4>Copyright Stuff</h4>
</div>
</script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="lib/jquery-1.8.3.js"></script>
<script src="lib/jquery.mobile/jquery.mobile-1.4.2.min.js"></script>
<script src="lib/jquery-ui-1.10.4.custom.min.js"></script>
<script src="lib/underscore-min.js"></script>
<script src="lib/backbone-min.js"></script>
<script src="lib/backbone.touch.min.js"></script>
<script src="lib/handlebars.js"></script>
<script src="templates/homeView.js"></script>
<script src="templates/page1View.js"></script>
<script src="js/main.js"></script>
<link rel="stylesheet" type="text/css" href="css/jquery-ui-1.10.4.custom.min.css" />
<link rel="stylesheet" type="text/css" href="css/jquery.mobile-1.4.2.min.css"/>
</head>
<body></body>
</html>
main.js:
var AppRouter = Backbone.Router.extend({
routes:{
"home":"home",
"page1" : "page1",
},
home:function () {
this.changePage(new HomeView());
},
page1:function () {
this.changePage(new Page1View());
},
changePage:function (page, argumentos) {
if (this.currentPage)
this.currentPage.close();
this.currentPage = page;
$(page.el).attr('data-role', 'page');
var render = page.render();
$('body').append($(page.el));
var transition = 'slide';
var reverse = false;
if(argumentos && argumentos[0] == 'true'){
reverse = true;
}
$.mobile.changePage($(page.el), {transition: transition, reverse: reverse});
}
});
$(document).ready(function () {
Handlebars.registerPartial("header", $("#header-partial").html());
Handlebars.registerPartial("footer", $("#footer-partial").html());
var app = new AppRouter();
Backbone.history.start();
Backbone.history.navigate('home', {trigger: true});
Backbone.View.prototype.close = function() {
this.unbind();
this.remove();
}
});
homeView.js
var HomeView = Backbone.View.extend({
template: Handlebars.compile($("#home-tpl").html()),
render:function (eventName) {
$(this.el).html(this.template({pageTitle:"home"}));
return this;
},
events : {
"tap #page1Link" : "gotoPage1",
},
gotoPage1 : function() {
Backbone.history.navigate('page1', {trigger: true});
}
});
page1View.js
var Page1View = Backbone.View.extend({
template: Handlebars.compile($("#page1-tpl").html()),
render:function (eventName) {
$(this.el).html(this.template({pageTitle: "page1"}));
return this;
},
events : {
"click div#header a" : "back",
},
back : function() {
Backbone.history.navigate('home', {trigger: true});
},
});
如果我在两个视图之间不断更改,那么DOM节点计数会表现出以下行为(内存下降的图形部分是我点击以强制进行垃圾收集的部分):
我是这些技术的初学者,所以我想我做错了什么。我已经搜索过这个问题的答案了,但我发现我已经完成了所有事情(为每个被销毁的视图调用remove()和unbind())。
那么,我该如何处置这些节点?
答案 0 :(得分:0)
我猜你还没有删除$ .mobile.changePage上的引用。
$.mobile.changePage($(page.el), {transition: transition, reverse: reverse});
但是,我不熟悉jquery-mobile。但是我对backbonejs代码有一些评论。
我的建议是在index.html上添加一个DIV元素,它充当你的应用程序的视口。然后,您可以在此DIV上绑定所有视图对象。
的index.html
<div id="myviewport"></div>
HomeView.js
var HomeView = {
....
initialize: function () {
this.$el = $("#myviewport");
},
....
};
你也可以做类似的渲染
//main.js
//since page.render() return this, you can chain them up
//In other
$("body").append(page.render().$el);
答案 1 :(得分:0)
Backbone.View.prototype.close = function() {
this.undelegateEvents();
Backbone.Validation.unbind(this);
this.$el.removeData().unbind().empty();
if (this.model) {
this.model.off();
this.model.destroy({ silent: true });
}
};
undelegateEvents是取消定位所有事件的主要方法 Backbone.Validation.unbind(本);取消绑定骨干验证