使用Backbone.js渲染布局

时间:2010-11-30 02:15:51

标签: javascript backbone.js

如果您使用Backbone.js和jQuery构建单页Web应用程序(SPWA) - 例如 - 两个控制器,每个控制器都需要一个独特的页面布局,您将如何呈现布局?

  • ControllerA是三列布局。
  • ControllerB是两列布局。
  • 默认路由激活ControllerA.Welcome() - 初始渲染。
  • 两个控制器在其列中呈现的不同视图利用了所有Backbone.js模型/视图的优点。

问题

当用户请求映射到ControllerB的路由时,整个页面布局需要更改为不再使用ControllerA布局。这将隐藏ControllerA的布局并显示ControllerB的布局 - 或者,如果DOM中尚未存在布局,则呈现布局。

我的第一个想法

您是否会使用Backbone.js视图渲染布局,然后使用模型绑定视图渲染每一列?

我的第二个想法

您是否会向控制器添加一个设置/布局方法,该方法使用jQuery呈现布局,然后允许负责路由的操作做到这一点?在控制器中使用jQuery对我来说感觉不错,但是,我希望控制器负责确保正确的布局对于它的路径是可见的。

这是我的第二个想法的片段:

var Controller = Backbone.Controller.extend
({
    routes :
    {
       "" : "welcome" // default action
    }
    /** Constructor **/
    ,initialize: function(options)
    {
        console.log('Workspace initialized');               
    }
    // LAYOUT
    ,renderLayout : function ()
    {
        console.log('Rendering Layout.');
        var $ = window.$;
        var layout = require('js/layout/app/big_menu');
        $(layout.parent).html(layout.html);
    }
    // ACTIONS
    /** Default Action **/
    ,welcome : function ()
    {
        this.renderLayout();
        console.log('Do the whole model/view thing...');
    }
});

谢谢

感谢您抽出宝贵时间作出回应。我很感激!

4 个答案:

答案 0 :(得分:18)

我倾向于同意朱利安 - 让你的布局尽可能无状态是很好的。至少,所有东西总是以骨架的形式排列在页面上。当需要显示特定的布局或配置时,您可以懒惰地呈现其内容,并使用CSS显示UI的该部分。相互排斥的CSS类对此非常有用,例如:“projects-open”,“documents-open”,“notes-open”。

答案 1 :(得分:7)

我更喜欢在页面上放置应用程序的框架。因此,您可以在页面上使用不同元素的完整布局,并根据这些元素创建主干视图,以便正确布局。

当你有一个布局时,这种方法很有效,当你有多个布局时,事情变得有趣。您可以将所有布局放在页面上,并根据您的逻辑隐藏不同的配置。您可以看到布局是层次结构的初始视图。因此,您渲染布局,然后加载视图。

没有真正的一种方法可以做到这一点。各有利弊。我不会做的一件事是在控制器中渲染布局。我将所有渲染和html放在视图中,这样我就可以处理控制器和模型上的逻辑(想想MVC)。

答案 2 :(得分:6)

我正在使用backbone.js设计基于模块的Intranet系统,我基本上在文档加载时使用以下算法。

  • 创建appController,app的单例控制器。
  • appController创建mainView,这是负责呈现页面骨架并处理页面上持久性项目点击的视图(登录/注销按钮等)
  • mainView为页面的不同部分,导航,面包屑,标题,工具栏,contentContainer等创建了许多childView。这些是应用程序的固定装置,它们不会更改,尽管它们各自的内容都有。 contentArea特别可以包含任何布局。
  • appController运行已注册的模块,为每个模块启动mainModuleController。这些都有名称空间路由模式。
  • Backbone.history.start()

moduleControllers都可以在init上访问appController。捕获哈希位置时,它们会将pageChange事件发送到包含pageManifest对象的appController。 pageManifest对象包含设置相应视图所需的所有信息,例如面包屑信息,标题信息,最重要的是,对实例化的contentView的引用。 appController使用pageManifest中的信息来设置不同的持久视图,删除contentContainer中的前一个contentView,并将模块提供的contentView插入到容器中。

这样,不同的设计人员可以处理不同的模块,他们必须知道的是pageManifest对象的规范以及contentView的外观。他们可以自己设置复杂的路由系统,使用他们自己的模型和自定义的contentViews(虽然我们计划有一个listViews,objectViews等库继承)。

我们现在处于设计阶段,所以我无法保证这是我们最终会使用的设计,或者我们没有找到任何漏洞,但从概念上讲,我们认为这是合理的。评论

答案 3 :(得分:1)

无论Backbone还是其他任何js框架/库,我都有完全相同的问题。

想象一下,你有一个SIGN IN FORM视图,它需要一个单独的列布局,然后将视图注入到那个单个div中。

然后,一旦成功登录,就会以某种方式呈现另一个布局(比如说一个HEADER区域,FOOTER区域,LEFT区域,然后是MAIN区域(右列)。

标题可能包含LOGO视图(如果它具有功能)和GLOBAL / USER MENU视图。 LEFT区域将包含PRIMARY NAV视图。

然后进一步复杂化。 PRIMARY NAV视图中的每个链接都会加载一个新的子布局,以便进一步注入自己的视图。

我不希望常规控制器/视图关心当前呈现的布局,只是它们的容器元素存在并且可以注入。

我想过以一种聪明的方式使用路线(不是传统意义上的):

function LayoutController() {
App.addRouteMatcher("/sign_in/*", this.renderSignInLayout); // single column
App.addRouteMatcher("regex to represent anything but sign_in", this.renderMainLayout); // header, footer, primary nav, main zone
App.addRouteMatcher("/section1/*", this.renderSubLayoutForSection1); // puts a 1 column layout in the main zone
App.addRouteMatcher("/section2/*", this.renderSubLayoutForSection2); // puts a 2 column layout in the main zone 
}

意思是如果路由是“/ section1 / whatever / sub / page / within / section / 1”,则两个路由匹配“regex以表示除sign_in之外的任何内容”和“/ section1 / *”都会运行,这意味着主要布局将被渲染,然后在有意义的情况下渲染section1子布局。

然后所有其他普通控制器都使用传统意义上的路线。

需要有一种很好的方法来管理布局,并确保安全地拆除这些布局,子布局和视图,以确保处理内存泄漏等原因。

很想听到有人设计并实现了优雅的东西。