【问题标题】:How do i pass a user object to a partials in ejs?如何将用户对象传递给 ejs 中的部分?
【发布时间】:2015-09-30 15:34:37
【问题描述】:

我正在尝试在导航栏上呈现用户名,但该导航栏位于部分文件夹中,并且 node.js 中的所有路由都不会呈现 navbar.ejs,因为它只是部分文件夹。我正在使用 ejs-mate 库来拥有一个可重用的布局组件以用于其他的 html 组件,这样我就不需要复制和粘贴代码(遵循 DRY 原则),为什么?因为ejs没有内置可复用布局组件的特性,其他库也不由其他开发者维护。

目前

我有两条路线

app.get('/', passport.isAuthenticated, function(req, res) {
   res.render('home' {
     user: req.user
   });
});

app.get('/anotherRoute', function(req, res) {
   res.render('test');
});

我有两个 ejs 文件

home.ejs

<%- layout('boilerplate') %>

<h1>Home Page</h1>

另一个.ejs

<%- layout('boilerplate') %>

<h1>Another Page</h1>

这两个ejs文件使用boilerplate.ejs进行布局,所以我不会一遍又一遍地复制和粘贴相同的代码。

boilerplate.ejs - 在这个文件中,我包含了导航栏和其他一些部分。

<!DOCTYPE html>
<html lang="en">
<head>

    <% include ./partials/navbar %>
</head>
<body>

    <header>
        <% include ./partials/header %>
    </header>

<div class="container">
    <main>
        <%- body -%>
    </main>

    <footer>
        <% include ./partials/footer %>
    </footer>
  </div>

</body>
</html>

这是navbar文件,看看navbar-right类,

if user is logged in render name 
else render about and signup

navbar.ejs

<nav class="navbar navbar-default" role="navigation">
    <div class="container-fluid">

        <div class="navbar-header">
            <a class="navbar-brand" href="/">
                StartupClone
            </a>
        </div>

        <ul class="nav navbar-nav navbar-right">
            <li><a href="/">About</a></li>
            <% if (!user) { %>

            <li><a href="/signup">Signup</a></li>
            <li><a href="/login">Login</a></li>
        </ul>
        <% } else{ %>
          <li><a><%= user.profile.name %></a></li>
       <% } %>
    </div>
</nav>

现在的问题是,它只适用于我将用户对象传递给的路由,而不是其他路由。我知道我必须将用户的对象传递给每条路线,但这并不好,因为我必须再次将代码复制并粘贴到每条路线中,这违反了 DRY 原则,

想象一下,如果有 40 条路线需要使用该导航栏,那对我来说将是一场噩梦 :(

如果你们对如何破解此问题有任何想法,请随时提出如何解决此问题的想法。

【问题讨论】:

标签: node.js ejs


【解决方案1】:

必须在视图上传递您尝试访问的对象。 您可以做的一件事是将用户对象存储在会话中并在视图中检查用户对象的会话。 这样你就必须只传递会话对象,至少我使用这个技巧来解决这个问题。

在您的中间件 passport.isAuthenticated 中成功登录时保存用户对象

module.exports.isAuthenticated = function(req, res, next) {
  /*
     check for valid credentials 
  */
  if (success)
  {
    req.session.user = foundUserInfo;
  }
  next();
}

在你的局部视图中

<!-- navbar.ejs -->
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">

    <div class="navbar-header">
        <a class="navbar-brand" href="/">
            StartupClone
        </a>
    </div>

    <ul class="nav navbar-nav navbar-right">
        <li><a href="/">About</a></li>
        <% if (!session.user) { %>

        <li><a href="/signup">Signup</a></li>
        <li><a href="/login">Login</a></li>
    </ul>
    <% } else{ %>
      <li><a><%= session.user.profile.name %></a></li>
   <% } %>
</div>

现在您只需为每个路由传递会话对象。

app.get('/', passport.isAuthenticated, function(req, res) {
   res.render('home' {
      user: req.user,
      session: req.session
   });
});

app.get('/anotherRoute', function(req, res) {
   res.render('test', {session: null});
});

【讨论】:

    【解决方案2】:

    必须为每个res.render() 调用传递一个具有已使用属性的对象,这是没有办法的。它甚至在 ejs-mate 的文档中的使用示例中。

    话虽如此,有一种方法可以让您的代码保持干燥。使用在输入对象上设置共享属性的函数,然后为每个路由设置它所需的唯一属性:

    function setSharedProperties(req, data) {
       if(!(data instanceof Object)) {
          data = {};
       }
       data.user = req.user;
    
       return data;
    }
    
    app.get('/', passport.isAuthenticated, function(req, res) {
       res.render('home', setSharedProperties(req))
    });
    
    app.get('/anotherRoute', function(req, res) {
       res.render('test', setSharedProperties(req, {prop1: val1}));
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-26
      • 2012-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-08
      • 1970-01-01
      • 2018-04-04
      相关资源
      最近更新 更多