在Backbone中多次初始化View

时间:2017-10-09 09:05:33

标签: javascript backbone.js

我正在Backbone中构建一个网站,其网站结构类似于Youtube,因为当您使用页面链接更改页面时,只会重新加载一部分DOM(即非导航组件)整个文件。

因此,当用户使用我网站上的链接访问子页面时,Backbone将发出一个AJAX调用并接收子页面的HTML,如下所示:

<section id="SubpageView">...</section>
<script>

// Defines the view that controls #SubpageView.
if(typeof SubpageView !== 'undefined') {

    // If this is the first time the page is loaded, create class.
    var SubpageView = Backbone.Model.extend({
        el: '#SubpageView',
        ...
    });

}

MainView.currentSubpage = new SubpageView();
</script>

多次调用SubpageView()有任何缺点(即僵尸视图,内存泄漏等)吗?在我看来,使用 el 而不是 tagName 定义一个View元素是用于仅使用一次的元素。

注意:我知道单页网页应用程序通常将所有模板都放在持久性DOM中,所有HTML都是使用客户端模板处理的。但是因为我设计的网站在没有pushState()的情况下降级为传统的服务器端渲染,或者当Javascript被禁用时,我不想将我的所有模板都烘焙到持久性DOM中。

1 个答案:

答案 0 :(得分:2)

这是一个很好的问题 - 我认为很多人都忽略了这个问题而且会引发问题。 &#34; Zombie Views&#34;是一个伟大的描述。我说你是对的他们可能会导致问题:

  • 您正在维护(可能很大)不再需要的对象实例。
  • 您的僵尸视图实例仍然可以引用仍在使用的现有对象,并可能导致意外行为。

如果您使用Backbone的事件哈希,那么最后一点尤其重要,例如:

events: {
    'click .someButton': 'someMethod',
    // ...
},

由于您正在重用el选择器(我认为您应该这样做),所有僵尸视图的事件将保持活动状态,并在不需要时触发视图的功能。这可能意味着重复行为或其他完全意外的结果。

至于解决方案,我认为你有两个选择:一个是在更新之前销毁你的旧视图实例。默认的remove方法实际上删除了您不想要的el ... undelegateEvents可能有所帮助。 Backbone并没有真正干净的方式去做所需的事情,所以你最终会自己编写一些代码。

我认为更好的选择是使用新数据(collectionmodel,其他实例数据或其他任何适当的数据重复使用现有的视图实例。

当您更改页面的子视图时,您可能会传入一些变量,比如获取的html:

$.get('/templates/someView.html', function(html) {
    Mainview.currentSubpage = new SubpageView(html);
});

......或类似的东西。相反,我建议使用方法来编写更新现有​​实例,例如:

$.get('/templates/someView.html', function(html) {
    Mainview.currentSubpage.resetPage(html);
});

您可以将resetPage方法写入SubpageView,以满足您的需求。这当然不仅仅适用于html传递,我只是以此为例。