【问题标题】:What is the proper way to check for existence of variable in an EJS template (using ExpressJS)?检查 EJS 模板中是否存在变量的正确方法是什么(使用 ExpressJS)?
【发布时间】:2011-07-19 08:34:19
【问题描述】:

在EJS github页面上,只有一个简单的例子: https://github.com/visionmedia/ejs

例子

<% if (user) { %>
    <h2><%= user.name %></h2>
<% } %>

这似乎是在检查一个名为 user 的变量是否存在,如果存在,做一些事情。呃,对吧?

我的问题是,如果用户变量不存在,为什么 Node 会抛出 ReferenceError?这使得上面的例子毫无用处。检查变量是否存在的适当方法是什么?我是否应该使用 try/catch 机制并抓住那个 ReferenceError?

ReferenceError: user is not defined
    at IncomingMessage.anonymous (eval at <anonymous> (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:140:12))
    at IncomingMessage.<anonymous> (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:142:15)
    at Object.render (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:177:13)
    at ServerResponse.render (/usr/local/lib/node/.npm/express/1.0.7/package/lib/express/view.js:334:22)
    at Object.<anonymous> (/Users/me/Dropbox/Projects/myproject/server.js:188:9)
    at param (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:146:21)
    at pass (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:162:10)
    at /usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:152:27
    at Object.restrict (/Users/me/Dropbox/Projects/myproject/server.js:94:5)
    at param (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:146:21)

我知道我可以通过在我的服务器代码中简单地添加一个“用户”局部变量来消除这个错误,但这里的重点是我想在运行时使用你的每一天检查这些变量是否存在if/else nullcheck 类型模式。一个不存在的变量的例外对我来说似乎很荒谬。

【问题讨论】:

    标签: node.js express ejs


    【解决方案1】:

    就像你在 js 中做任何事情一样,typeof foo == 'undefined',或者因为“locals”是包含它们的对象的名称,你可以做if (locals.foo)。这只是原始的 js:p

    【讨论】:

    • 我开始怀疑我手上是否有更大的问题。这也会引发参考错误:
    • @Aasay alert 是浏览器 window 对象的一部分,在 node.js 中不可用。替代方案是console.log,虽然我不知道它是否在 ejs 模板中可用,除非你通过 locals 传递它。
    • @Zikes 在这种情况下,我专门寻找 EJS,所以它在浏览器页面上。但是,就像 TJ 所说, typeof foo == 'undefined' 有效。我了解到,如果 foo 已定义但为 null 或为空,我还可以添加一个简单的 !!foo。
    • 这个有简写吗?为什么 EJS 不简单地尊重 if (foo) 案例?
    • if (locals.user){ } FTW
    【解决方案2】:

    尝试在变量前添加 locals

    示例:if(locals.user){}

    【讨论】:

      【解决方案3】:
      <% if (locals.user) { %>
      
       // Your logic goes here 
      
      <% } %>
      

      【讨论】:

        【解决方案4】:

        您可以创建一个检查“obj === void 0”的视图助手,这个是针对 express.js 的:

        res.locals.get = function() {
            var args = Array.prototype.slice.call(arguments, 0);
            var path = args[0].split('.');
            var root = this;
            for (var i = 0; i < path.length; i++) {
                if(root[path[i]] === void 0) {
                    return args[1]?args[1]:null;
                } else {
                    root = root[path[i]];
                }
            };
            return root;
        }
        

        然后在视图中像这样使用它

        <%- get('deep.nested.non.existent.value') %>  //returns: null
        <%- get('deep.nested.non.existent.value', "default value") %> //returns: default value
        

        【讨论】:

        • 不知道为什么这被否决了,在我看来它相当优雅。
        • &lt;%=&lt;%-有什么区别?
        • @NobleUplift 根据the documentation,在“标签”下:&lt;%= HTML 首先转义值; &lt;%- 输出未转义的值。所以&lt;b&gt;在使用&lt;%-时会变成一个粗体标签,而在使用&lt;%=时只是文本“
        • 谢谢!我不知道
        • 我知道这是一篇过时的帖子,但我该如何实现呢?我自己尝试过,但找不到如何正确地将其转换为助手。谢谢。
        【解决方案5】:

        要检查用户是否已定义,您需要这样做:

        <% if (this.user) { %>
           here, user is defined
        <% } %>
        

        【讨论】:

        • 这在最新的 EJS 库 (1.0.0) 中不起作用。虽然是有效的 Javascript,但 EJS 将拒绝按预期行事。
        • 对我不起作用。即使我已经定义了foo,else 子句仍然会被评估。使用 EJS 2.3.4 测试编辑:使用 locals 代替 this 有效
        【解决方案6】:

        在使用 mongoose/express/ejs 和 mongoose 的 populate() 建立 2 个集合之间的关系时,我遇到了同样的问题,在这种情况下 admins.user_id 存在但与不存在的用户相关。 _id.
        所以,找不到原因:

        if ( typeof users.user_id.name == 'undefined' ) ...
        

        因“无法读取属性 'name' of null”而失败 然后我注意到我需要像这样进行检查:

        if ( typeof users.user_id == 'undefined' ) ...
        

        我需要检查“名称”的“容器”,所以它起作用了!
        之后,它的工作原理相同:

        if ( !users.user_id ) ...  
        

        希望对你有帮助。

        【讨论】:

        • 无论如何,不​​敢相信关于 EJS 的官方文档如此之少......自 2010 年以来他们没有更新他们的 documentation !!!
        【解决方案7】:

        来到这个页面寻求答案,但我想出了一个更短的内联语法:

         <h2><%= user.name ? property.escrow.emailAddress : '' %></h2>
        

        【讨论】:

        • 这样使用很危险,因为如果对象'us​​er'没有'name'属性,ejs渲染会失败。
        【解决方案8】:

        我所做的只是传递一个我称为 'data' = '' 的默认对象并将其传递给我所有的 ejs 模板。 如果您需要将真实数据传递给 ejs 模板,请将它们添加为“数据”对象的属性。

        这样,'data' 对象总是被定义并且你永远不会收到未定义的错误消息,即使 'data' 的属性存在于您的 ejs 模板中但不存在于您的节点快速路由中。

        【讨论】:

          【解决方案9】:

          对于您的if 声明,您需要使用typeof

          <% if (typeof user == 'object' && user) { %>
          
          <% } %>
          

          【讨论】:

            【解决方案10】:

            这可能对某人有所帮助。

            <p><%= locals?.message %></p>
            

            <p><%= locals.message || '' %></p>
            

            【讨论】:

              【解决方案11】:

              我有同样的问题,幸运的是,我发现 JS 中也有一个短路函数(我知道 Ruby 和其他一些语言中有一个)。

              在我的服务器/控制器端(来自 Node.js/Express):

              return res.render('result', {survey_result : req.session.survey_result&&req.session.survey_result.survey }); 
              

              看看我在那里做了什么?在可能未定义的变量(即request.session.survey_result 对象,可能有也可能没有表单数据)之后的 && 是 JS 中的短路符号。如果 && 左边的部分不是未定义的,它所做的只是评估 && 后面的部分。当左侧部分为undefined 时,它也不会抛出错误。它只是忽略它。

              现在,在我的模板中(请记住,我将对象 req.session.survey_result_survey 对象作为 survey_result 传递给我的视图)然后我将字段呈现为:

              <table>
                  <tr>
                      <td> Name:</td>
                      <td> <%=survey_result&&survey_result.name%></td>
                  </tr>
                  <tr>
                      <td> Dojo Location:</td>
                      <td> <%=survey_result&&survey_result.dojo_loc%></td>
                  </tr>
                  <tr>
                      <td> Favourite Language:</td>
                      <td> <%=survey_result&&survey_result.fave_lang%></td>
                  </tr>
              

              我在那里也使用了短路,只是为了安全起见。

              当我用以前建议的方法尝试时,只是:

              <% if (typeof survey_result !== undefined) { %>
              ... <!-- some js and/or html code here -->
              <% } %>
              

              有时,它仍会尝试评估 IF 语句中的属性...也许有人可以解释为什么?

              另外,我想更正 undefined 需要不带单引号,正如我在前面的示例中看到的那样。因为条件永远不会计算为true,因为您将字符串值'undefined' 与数据类型undefined 进行比较。

              【讨论】:

                【解决方案12】:

                你可以使用这个技巧:

                user.name // stops code execution,if user is undefined
                (scope.user||0).name // === undefined
                

                其中范围是用户的父对象

                【讨论】:

                  【解决方案13】:

                  如果你打算经常使用同一个对象,你可以使用这样的函数:

                  <% function userObj(obj){
                      //replace user with what you name your object
                      if(typeof user === 'object'){
                          let result = user;
                          if(obj){
                              obj = obj.split('.');
                              for(let i = 0; i < obj.length; i++){
                                  if(obj[i] && obj[i].trim() !== '' && result[obj[i]]){
                                      result = result[obj[i]];
                                  }else{
                                      result = false;
                                      break;
                                  }
                              }
                          }
                          return result;
                      }
                      return false;
                  } %>
                  

                  用法:

                  <% if(userObj('name')){
                      <h2><%= userObj('name') %></h2>
                  } %>
                  

                  【讨论】:

                    【解决方案14】:

                    我想出了另一个解决方案。

                    <% if(user){ %>
                       <% if(user.name){ %>
                         <h1><%= user.name %></h1>
                    <%}}%>
                    

                    我希望这会有所帮助。

                    【讨论】:

                    • 您可以在一次评估中加入两个条件:if (user &amp;&amp; user.name)
                    【解决方案15】:

                    我在Joe Andrieu's blog 上找到了我认为更好的解决方案:

                    <%= user.name ? user.name : '' %>
                    

                    这适用于比其他答案更多的情况(即,当您需要检查单个属性是否存在时)。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2019-12-11
                      • 2019-09-16
                      • 2016-11-05
                      • 1970-01-01
                      • 1970-01-01
                      • 2020-05-30
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多