检查 EJS 模板中是不是存在变量的正确方法是啥(使用 ExpressJS)?
Posted
技术标签:
【中文标题】检查 EJS 模板中是不是存在变量的正确方法是啥(使用 ExpressJS)?【英文标题】: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 类型模式。一个不存在的变量的例外对我来说似乎很荒谬。
【问题讨论】:
【参考方案1】:就像你在 js 中做任何事情一样,typeof foo == 'undefined'
,或者因为“locals”是包含它们的对象的名称,你可以做if (locals.foo)
。这只是原始的 js:p
【讨论】:
我开始怀疑我手上是否有更大的问题。这也会引发参考错误: @Aasayalert
是浏览器 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
【讨论】:
不知道为什么这被否决了,在我看来它相当优雅。<%=
和<%-
有什么区别?
@NobleUplift 根据the documentation,在“标签”下:<%=
html 首先转义值; <%-
输出未转义的值。所以<b>
在使用<%-
时会变成一个粗体标签,而在使用<%=
时只是文本“”
谢谢!我不知道
我知道这是一篇过时的帖子,但我该如何实现呢?我自己尝试过,但找不到如何正确地将其转换为助手。谢谢。【参考方案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>
【讨论】:
这样使用很危险,因为如果对象'user'没有'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 && user.name)
【参考方案15】:
我在Joe Andrieu's blog 上找到了我认为更好的解决方案:
<%= user.name ? user.name : '' %>
这适用于比其他答案更多的情况(即,当您需要检查单个属性是否存在时)。
【讨论】:
以上是关于检查 EJS 模板中是不是存在变量的正确方法是啥(使用 ExpressJS)?的主要内容,如果未能解决你的问题,请参考以下文章
在 Express/EJS 模板中,循环数组的最简洁方法是啥?
检查模板中是不是存在变量,如果不存在则不会在记录器中导致错误