在EJS模板中检查变量是否存在的正确方法是什么(使用ExpressJS)?

问题描述 投票:96回答:10

在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
10个回答
119
投票

与js,typeof foo == 'undefined'中的任何内容相同,或者因为“locals”是包含它们的对象的名称,您可以执行if (locals.foo)。这只是原始的js:p


0
投票

我有同样的问题,幸运的是,我发现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中的短路符号。它的作用是仅评估&&后面的部分,如果&&左边的部分未定义。当左侧部分是Qazxswpoi时,它也不会抛出错误。它只是忽略它。

现在,在我的模板中(记住我将对象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声明中的属性......也许有人可以提供解释为什么?

此外,我想纠正<% if (typeof survey_result !== undefined) { %> ... <!-- some js and/or html code here --> <% } %> 需要没有单引号,正如我在前面的例子中看到的那样。因为条件永远不会评估为undefined,因为您将字符串值true与数据类型'undefined'进行比较。


20
投票

尝试使用locals预先添加变量

示例:if(locals.user){}


13
投票
<% if (locals.user) { %>

 // Your logic goes here 

<% } %>

11
投票

您可以创建一个查看“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

11
投票

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

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

5
投票

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

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

失败了“无法读取属性'名称'为null”然后我注意到我需要像这样进行检查:

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

我需要检查“名称”的“容器”,所以它有效! 在那之后,这也是一样的:

if ( !users.user_id ) ...  

希望能帮助到你。


2
投票

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

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

1
投票

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

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

<% } %>

0
投票

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

这样,“数据”对象始终被定义,并且您永远不会得到未定义的错误消息,即使您的ejs模板中存在“数据”属性,但节点快速路径中也不存在。

© www.soinside.com 2019 - 2024. All rights reserved.