流星模板层次结构和路由逻辑冲突

时间:2015-03-06 03:02:10

标签: meteor iron-router meteor-accounts

我的应用包含两个页面,主页和信息中心。在主页上,我想显示登录(顶部导航)和注册(主体)。如果用户已登录,则显示仪表板。在仪表板上我想显​​示Logout选项。注销时显示主页。

问题:当我尝试更新信息中心模板时,所有内容最终都会直接进入导航栏。同样令人困惑的是,主页页面中的正文内容仍在“仪表板”页面中呈现。我显然忽略了一些事情,但我无法判断我的代码是错误还是我对模板和路线的理解。

使用中:Iron-Router,Accounts-UI和Accounts-password,Twbs:bootstrap。

下面插入三个主要模板Master,Homepage和Dashboard。

提前感谢您提供的任何帮助!

主屏幕模板,如果已登录逻辑

<template name="MasterLayout">
    {{> yield}}
    <nav class="navbar navbar-inverse navbar-fixed-top">
    <div class="container">
      <div class="navbar-header">
        <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
          <span class="sr-only">Toggle navigation</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="#">THE BRAND</a>
      </div>
      <div id="navbar" class="navbar-collapse collapse">
        {{#if currentUser}}
          {{> Dashboard}}
        {{else}}
          {{> Login}}
        {{/if}}
      </div><!--/.navbar-collapse -->
    </div>
  </nav>
</template>

首页包含主要内容

<template name="Homepage">
  <div class="jumbotron">
    <div class="container">
      <h1>Get it now..</h1>
      <p>Donec id elit</p>
      {{#if currentUser}}
        hello
      {{else}}
        {{> Register}}
      {{/if}}
    </div>
  </div>
</template>

信息中心包含占位符文字

<template name="Dashboard">
  <ul class="nav navbar-nav">
    <li class="navbar-text">Navigation Placeholder</li>
    <li><a href="#" class="logout">Logout</a></li>
  </ul>
</template>

我创建了以下控制器;

主页

HomepageController = RouteController.extend({
  layoutTemplate: 'MasterLayout',

  subscriptions: function() {
  },

  action: function() {
    this.render('Homepage');
  }
});

控制台

DashboardController = RouteController.extend({
  layoutTemplate: 'Dashboard',

  subscriptions: function () {
  },

  data: function () {
  },

  action: function () {
    this.render('Dashboard', { /* data: {} */});
  }
});

2 个答案:

答案 0 :(得分:2)

定义路径控制器的方式存在很多问题,但没有问题。当我第一次使用Iron-Router时,我对如何正确设置它们感到同样困惑,但希望在我提出建议后,事情会变得更加清晰,就像我在使用Iron-Router之后为我做的那样

首先,由于您似乎只打算使用名为MasterLayout的一个布局模板,我建议您在全局级别为应用程序定义布局模板,如下所示:

    Router.configure({
        layoutTemplate: 'MasterLayout'
    });

这可确保MasterLayout模板用于所有路径,并且为用户当前所处的路线定义的模板将在该模板的yield区域中呈现。至于如何正确构建MasterLayout模板,因为您使用的是Bootstrap navbar构造,我建议您构建MasterLayout模板,如下所示:

    <template name="MasterLayout">
        <header>
            <nav class="navbar navbar-inverse navbar-fixed-top">
                <div class="container">
                    <div class="navbar-header">
                        <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                            <span class="sr-only">Toggle navigation</span>
                            <span class="icon-bar"></span>
                            <span class="icon-bar"></span>
                            <span class="icon-bar"></span>
                        </button>
                        <a class="navbar-brand" href="#">THE BRAND</a>
                    </div>
                    <div id="navbar" class="navbar-collapse collapse">
                        {{> loginButtons align="right"}}
                    </div>
                </div>
            </nav>
        </header>
        <article>
            {{> yield}}
        </article>
    </template>

我建议将整个navbar构造放入<header>元素,同时将布局模板的yield区域放在article元素中。实际上,您可以将这两个不同的部分放入您想要的任何类型的标签中,但我建议采用这种方式,以便正确使用HTML5标签并适当地分离页面。

如前所述,yield区域是插入当前路径模板的位置。此外,为了通过登录/注销按钮实现您的目标,只需将{{> loginButtons}}模板(由Accounts-UI包提供)引用放在navbar构造中。它将对当前用户是否登录或注销做出反应,并相应地显示带有文本的相应按钮。如果您希望将登录按钮与我喜欢的navbar构造的右侧对齐,可以将navbar-right类添加到<ul>元素并添加{{ 1}} align="right"模板引用的属性。这样可以确保当按钮一直拉到页面的右边缘时,登录按钮将打开到按钮左侧和页面上,而不是向右和离开页面。

为了实现上面指定的行为,我还建议定义两个路由,一个用于主页,一个用于仪表板,如下所示:

{{> loginButtons}}

通过定义这些路径,您可以在 Router.route('/', { name: 'Homepage', template: 'Homepage' }); Router.route('/dashboard', { name: 'Dashboard', template: 'Dashboard' }); 选项中定义它们引用的两个模板(加上可能的子模板),如下所示:

template

老实说,在这种情况下,您实际上不需要定义 <template name="Homepage"> ... {{> Register}} ... </template> <template name="Dashboard"> ... </template> <template name="Register"> ... </template> 模板,因为它已经在单独的Register模板中定义,并且您考虑放入Homepage的任何内容您可以直接将模板放入Register模板并保存并发症。这两个路由及其相关模板将提供您在上面指定的两个不同页面。

完成这项工作后,剩下要做的就是创建适当的Javascript,如下所示:

Homepage

如果用户注销,代码的第一部分会将用户重定向到 Router.onBeforeAction(function() { if(!Meteor.user()) { this.redirect('Homepage'); } else { this.next(); } }); if(Meteor.isServer) { Accounts.onLogin({ Router.go('Dashboard'); }); } 路由,而代码的第二部分会在用户登录时将用户重定向到Homepage路由。

实际上,您确实不需要像上面那样使用路径控制器。由于您只有两条路线,所以您只需定义两条路线就可以轻松逃脱,并根据需要添加适当的选项。

万一你还没有找到它,可以找到一个很好的铁路由器参考here

答案 1 :(得分:1)

  1. 在您的DashboardController中,将layoutTemplate: 'Dashboard',更改为layoutTemplate: 'MasterLayout',

  2. {{> Dashboard}}将在那里呈现信息中心模板。然后,当您致电this.render('Dashboard')时,也会使用信息中心模板代替{{> yield}}。你告诉它在2个地方渲染相同的模板。因此,在您的DashboardController中,将this.render('Dashboard', { /* data: {} */});更改为this.render('Homepage', { /* data: {} */});