Javascript 单页应用程序中的DOM节点不断增加
我正在开发一个使用主干网、把手和jquery mobile的单页应用程序。我面临一个问题,导致DOM节点不断上升,无论我如何清理它们 为了更好地演示这个问题,我创建了一个简单的程序,它的结构与我的应用程序完全相同,并且存在相同的问题。整个应用程序只有4个文件: index.html:Javascript 单页应用程序中的DOM节点不断增加,javascript,jquery-mobile,backbone.js,cordova,handlebars.js,Javascript,Jquery Mobile,Backbone.js,Cordova,Handlebars.js,我正在开发一个使用主干网、把手和jquery mobile的单页应用程序。我面临一个问题,导致DOM节点不断上升,无论我如何清理它们 为了更好地演示这个问题,我创建了一个简单的程序,它的结构与我的应用程序完全相同,并且存在相同的问题。整个应用程序只有4个文件: index.html: <!doctype html> <html> <head> <script id="home-tpl" type="text/x-handlebar
<!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>
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});
}
});
var HomeView = {
....
initialize: function () {
this.$el = $("#myviewport");
},
....
};
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())
那么,我如何处理这些节点呢?我想您还没有删除$.mobile.changePage上引用的节点
$.mobile.changePage($(page.el), {transition: transition, reverse: reverse});
但是,我不熟悉jquery mobile。但是我对backbonejs代码有一些评论
我的建议是在index.html上添加一个DIV元素,作为应用程序的查看端口。然后,所有视图对象都可以绑定到此DIV
index.html
<div id="myviewport"></div>
此外,还可以执行类似于渲染的操作
//main.js
//since page.render() return this, you can chain them up
//In other
$("body").append(page.render().$el);
取消LegateEvents是取消所有事件的主干的主要方法
主干。验证。解除绑定(此);取消绑定主干验证我从未使用过backbone.js或handlebar.js,但我看到您在close()函数中使用了这个.remove()。问题是,调用该函数时,“this”对象是什么。如果它是一个jQuery DOM对象,那么这个.remove()应该将它从DOM中删除。我会在该语句处停止调试器,并在调用close()时检查“this”是什么。此外,请检查Chrome Dev Tools中的“元素”选项卡,以确认在调用.remove()之后,预期的DOM元素正在被删除。我已经检查了“元素”选项卡,DOM正在被删除。我还不知道如何在javascript中使用调试器,但如果打印“this”,它会显示:
s{cid:“view7”,$el:jQuery.fn.jQuery.init[1],el:div.ui-page.ui-page-theme-a.ui-page-header-fixed.ui-page-footer-fixed.ui-page-active,constructor:function,template:function…}
。无需在每次处理路由时创建新视图。创建一次视图,然后在需要时更新。如果您需要从一个“页面”更改为另一个,只需清空el的html并将其他内容呈现到其中。另外,我不会重新定义已经为您定义的remove方法,因为主干视图已经在为您执行一些清理(解除绑定事件并从DOM中删除el)。我可以尝试只创建一次视图,但我认为清理代码是正确的,就像解释的那样。我不明白$.mobile.changePag
是如何泄漏内存的。我用的方法和他们主页上的例子一样,只是一个猜测。由于已调用this.close()和this.unbind()来取消对主干视图和jquery上dom节点的引用,因此剩余的引用是传递给$.mobile的引用。
//main.js
//since page.render() return this, you can chain them up
//In other
$("body").append(page.render().$el);
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 });
}
};