javascript 使用express时在EJS视图中查找当前url

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18501402/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 12:10:40  来源:igfitidea点击:

Finding current url inside EJS view when using express

javascriptnode.jsexpressejs

提问by Traveling Tech Guy

I'm using Express and EJS to serve pages. I'm using Bootstrap for the UI, specifically the navbar.

我正在使用 Express 和 EJS 来提供页面。我在 UI 中使用 Bootstrap,特别是导航栏。

I'd like to add an 'active'class to the current page's <li>item, to show the current page. However, I cannot find how to get the URL from within the EJS code rendering the page.

我想'active'为当前页面的<li>项目添加一个类,以显示当前页面。但是,我找不到如何从呈现页面的 EJS 代码中获取 URL。

I found 2 workarounds: I used included passing the page name as a parameter in the route's res.render('myview', {pageName: 'myView'});- which is not scalable and may cause issues.

我找到了 2 个解决方法:我使用了将页面名称作为参数传递到路由中的方法res.render('myview', {pageName: 'myView'});- 这是不可扩展的并且可能会导致问题。

The other way, was to use jQuery on the client side to add the 'active'class to the item upon page ready - but that means including this piece of script on every view + some useless client side cycles.

另一种方法是在客户端使用 jQuery'active'在页面准备好时将类添加到项目中 - 但这意味着在每个视图上都包含这段脚本 + 一些无用的客户端循环。

Having used several server side rendering languages before, I feel like I'm missing something. And the online EJS documentation is not that great.

之前使用过几种服务器端渲染语言,我觉得我错过了一些东西。在线 EJS 文档也不是很好。

Is there any way to find my current path/url from the EJS code?

有什么办法可以从 EJS 代码中找到我当前的路径/url?

Update:I took the top 2 suggestions, and passed the view name as a parameter to the view. I really liked @tandrewnichols' idea to calculate it automatically, but ultimately, it was easier to just copy-paste strings :)

更新:我采用了前 2 条建议,并将视图名称作为参数传递给视图。我真的很喜欢@tandrewnichols 自动计算它的想法,但最终,复制粘贴字符串更容易:)

采纳答案by tandrewnichols

In pretty much every node/express templating language I've used (ejs, kiwi, swig, jade), the answer is no. I've always just set a variable called "active" and then checked for it. As you say, it's not a great answer, though I don't know that scalability is the issue. If every url renders it's own view (or even if you have a common handler for view rendering), it shouldn't be that hard to say something like req.active = "Somepage". Another possibility would be to add middleware that does it for you based on the route. Something like

在我使用过的几乎所有节点/表达模板语言(ejs、kiwi、swig、jade)中,答案是否定的。我总是只设置一个名为“active”的变量,然后检查它。正如您所说,这不是一个很好的答案,尽管我不知道可扩展性是问题所在。如果每个 url 都呈现它自己的视图(或者即使您有一个用于视图呈现的通用处理程序),那么像req.active = "Somepage". 另一种可能性是添加中间件,根据路由为您执行此操作。就像是

app.use(function(req, res, next){
    req.active = req.path.split('/')[1] // [0] will be empty since routes start with '/'
    next();
});

Then you just make sure any routes that have a corresponding nav component use unique paths, like

然后,您只需确保具有相应导航组件的任何路由都使用唯一路径,例如

app.get('/students', ....)
app.get('/classes', ....)
app.get('/teachers', ....)
// etc.

EDIT: In response to your comment, I always throw ALL my view stuff into one object key inside req, and usually I name the key by whatever templater I'm using. So I would probably actually use the above example to set req.ejs.activeand then do

编辑:为了回应您的评论,我总是将我所有的视图内容放入一个对象键中req,并且通常我使用我使用的任何模板程序命名键。所以我可能实际上会使用上面的例子来设置req.ejs.active然后做

res.render('myview', req.ejs);

This method makes it much easier to separate logic out into multiple middleware functions and not have to pass a huge anonymous object to res.render.

这种方法可以更容易地将逻辑分离到多个中间件函数中,而不必将巨大的匿名对象传递给 res.render。

回答by hexacyanide

As far as I know, you can't do what you're asking for unless you modify EJSinternally. However, a less bothersome solution would be to pass the URL property of the request on each page invocation, rather than define it per route.

据我所知,除非你在内部修改EJS,否则你不能做你所要求的。然而,一个不太麻烦的解决方案是在每次页面调用时传递请求的 URL 属性,而不是按路由定义它。

app.get('/url', function (req, res) {
  res.render('view', {
    page: req.url,
    nav: {
      'Page 1': '/page1',
      'Page 2': '/page2',
      'Page 3': '/page3'
    }
  });
});

If you only wanted to get the first part of the URL and match it, then you could just call split('/')on req.url. You could then put a loop inside your template file to create the list for your navigation bar.

如果你只是想获得的URL的第一部分和与之相匹配的,那么你可以只调用split('/')req.url。然后,您可以在模板文件中放置一个循环来为导航栏创建列表。

<% nav.forEach(function(title) { %>
  <% if (nav[title] == page) { %>
    <li class="active">This part of the navigation bar is active.</li>
  <% } else { %>
    <li>This part of the navigation bar is normal.</li>
  <% } %>
<% }) %>

回答by antelove

index.js

索引.js

/* object menu */
const menu = [
    {
        name: 'Home',
        url: '/'
    },
    {
        name: 'About',
        url: '/about'
    }
]

/* route */
app.get( '/', function( request, response) {

    let data = {
        title: 'Home',
        url: request.url,
        menu: menu
    }

    response.render( 'home', data )

} )

app.get( '/about', function( request, response) {

    let data = {
        title: 'About',
        url: request.url,
        menu: menu
    }

    response.render( 'about', data )

} )

menu.js

菜单.js

    <% for ( let i in menu ) { %> // loop menu
        <% if ( menu[i].url == url ) { %> // match, add active in class

            <a class="active" href="<%= menu[i].url %>" ><%= menu[i].name %></a>

        <% } else { %>

            <a class="" href="<%= menu[i].url %>" ><%= menu[i].name %></a>

        <% } %>
    <% } %>