与 EJS 和 -not so- "local" 变量的范围作斗争
Struggle with EJS and scope of -not so- "local" variables
我想知道如何使用 EJS 模板编写我的 node.js 应用程序。
我实际上正在寻找一种在 partial/template.
中使用默认值定义局部变量的正确方法
我将快速说明它现在是否有效:
当我调用模板时,像这样:
<%- partial(__view.partialPath('tagPopover'), {
title_popover: sentence.nickname,
content_tag: '#' + sentence.nickname,
icon_popover: 'http://placehold.it/64x64'
}) %>
我以这种方式管理默认值,在 _tagPopover.ejs
部分:
title_popover = typeof title_popover != 'undefined' ? title_popover : ''
classes_tag = typeof classes_tag != 'undefined' ? classes_tag : 'tags'
icon_popover = typeof icon_popover != 'undefined' ? icon_popover : false
content_tag = typeof content_tag != 'undefined' ? content_tag : ''
我不使用 var
关键字,因为它根本不起作用,例如,如果我这样做:
var title_popover = typeof title_popover != 'undefined' ? title_popover : ''
然后 EJS 将解释 var title_popover
并在读取 变量 title_popover
的实际值之前创建一个局部变量 。所以我最终会得到一个 null
,即使我实际上发送了一个参数...
当我发现这一点时,我决定不使用 var
关键字...但我最近才发现,我用这种方式创建的所有变量实际上都是 global
!这意味着这是一个非常糟糕的解决方案,因为我可能最终会通过加载视图来重写全局变量!
我相信这将是一场斗争,我不希望我的观点默认 set/reset 全局变量(谁会?!)
你有什么解决办法吗?我已经考虑了几个,但我一个都不喜欢:
- 使用
var
关键字,但也在模式 之前为局部变量使用 以避免重置参数:var l_title_popover = typeof title_popover != 'undefined' ? title_popover : ''
。这看起来很糟糕而且令人困惑。
- 使用像
view.title_popover = typeof title_popover != 'undefined' ? title_popover : ''
这样的命名空间。我希望我的变量是局部变量,而不是全局变量,如果我这样做,我将拥有一些全局变量,它会一直存在于内存中。
你会如何处理?我很好奇,也许有一些 EJS 方法可以处理这个问题或帮助程序,我不知道。
有filters in ejs. Also see adding-filters的概念。
基本上我认为您正在寻找与此类似的东西。如果 res.locals 中存在,下面的代码将设置 title_popover,否则设置为 'some default value'
<%=: locals | get:'title_popover','some default value' %>
ejs.filters.get = function(obj, prop, default) {
return obj[prop] === undefined ? default : obj[prop];
};
我相信这是在 ejs 中最简单的方法,但可能还有一些其他方法。看起来像 this actually being discussed on a github ticket :)
编辑 - This blog post 似乎提供了一些使用下划线库的替代方案。看起来他们以某种方式将模板包装在布局中(我还没有完全理解这篇文章,但从表面上看似乎很有意义)。
不过我只用过上面的方法
EJS 不是一个好的模板,这是可以预料的,因为它非常古老且不活跃。也就是说,在传递变量时,JS 的模板引擎并不完全 well-featured。我正在使用 Sails 框架,我所做的只是将变量传递到我的路由设置(如果它们是硬编码的)或我的控制器(如果它们是动态的)中的视图。
也可以通过策略向 res.locals
提供标准路由设置。
例如,我在航行路线中有以下设置:
'GET /':{
controller: 'IndexController.js',
action: 'displayIndexPage',
title: 'Main page',
},
'GET /flowchart': {
controller: 'FlowchartController.js',
action: 'displayFlowchart',
title: 'Flowchart'
}, //...
然后我有一个策略viewToLocals.js
,代码如下:
module.exports = function(req, res, next) {
res.locals.view = req.options.title;
return next();
};
顺便说一句,这不会覆盖我从控制器或任何其他文件传递给视图的任何数据。如果我遇到你的问题,我能做的是这样的:
//setPageParamsPolicy.js
module.exports = function(req, res, next) {
res.locals.popovers = {
title: ('undefined') ? res.get('body').username : 'Default title', //or wherever you fetch data from
icon : ('undefined') ? res.get('body').avatar : 'www.site.com/defaultAvatar.jpg'
}
return next();
};
Sails 是基于 Express 构建的,因此这些信息可能会有用。但是请注意,帆策略适用于控制器操作,这意味着如果您定义一个简单的视图视图,它不会应用 - 您必须将它路由到特定的控制器。但是,您可以将此 object 放入路由中:
//routes.js
'GET /userpanel': {
view: 'userpanel',
locals = {
popover: {
title: ('undefined') ? res.get('body').username : 'Default title', //or wherever you fetch data from
icon : ('undefined') ? res.get('body').avatar : 'www.site.com/defaultAvatar.jpg'
}
}
}
我也对此感到疑惑,并得出结论,没有简单的方法可以做到这一点。但对我来说,Sails 提供了一个相对简单的解决方案,同时也相对简单易行。
如果您喜欢使用纯 JS 来处理事物,EJS 是一种出色的模板语言。该项目目前非常活跃。
NPM 上的 EJS 模块(现在是 v2)在这里积极维护:https://github.com/mde/ejs。 (不再维护旧的 v1 存储库。)
着陆点在这里:http://ejs.co
不应在模板中设置数据的默认值。模板应该只用于渲染。更好的方法是在传入数据之前对其进行预处理:
var defaultVals = {
foo: 'FOO',
bar: 'BAR'
};
// Mix in left to right: https://gist.github.com/mde/81b131ff6810ed7c4e0e
var dataObj = mixin({}, defaultVals, {bar: 'NOT BAR'});
// Outputs "FOO, NOT BAR"
ejs.render('<%= [foo, bar].join(", "); %>', dataObj);
顺便说一下,在 v2 中从 EJS 中删除了过滤器。它们是与嵌入式无关的非标准功能 JavaScript,并且很容易使用您自己的代码进行复制。
我在 ejs 中这样定义默认变量:
<% var username, password%>
<script>
var username = "<%= username %>",password = "<%= password %>" %>
</script>
我想知道如何使用 EJS 模板编写我的 node.js 应用程序。 我实际上正在寻找一种在 partial/template.
中使用默认值定义局部变量的正确方法我将快速说明它现在是否有效:
当我调用模板时,像这样:
<%- partial(__view.partialPath('tagPopover'), {
title_popover: sentence.nickname,
content_tag: '#' + sentence.nickname,
icon_popover: 'http://placehold.it/64x64'
}) %>
我以这种方式管理默认值,在 _tagPopover.ejs
部分:
title_popover = typeof title_popover != 'undefined' ? title_popover : ''
classes_tag = typeof classes_tag != 'undefined' ? classes_tag : 'tags'
icon_popover = typeof icon_popover != 'undefined' ? icon_popover : false
content_tag = typeof content_tag != 'undefined' ? content_tag : ''
我不使用 var
关键字,因为它根本不起作用,例如,如果我这样做:
var title_popover = typeof title_popover != 'undefined' ? title_popover : ''
然后 EJS 将解释 var title_popover
并在读取 变量 title_popover
的实际值之前创建一个局部变量 。所以我最终会得到一个 null
,即使我实际上发送了一个参数...
当我发现这一点时,我决定不使用 var
关键字...但我最近才发现,我用这种方式创建的所有变量实际上都是 global
!这意味着这是一个非常糟糕的解决方案,因为我可能最终会通过加载视图来重写全局变量!
我相信这将是一场斗争,我不希望我的观点默认 set/reset 全局变量(谁会?!)
你有什么解决办法吗?我已经考虑了几个,但我一个都不喜欢:
- 使用
var
关键字,但也在模式 之前为局部变量使用 以避免重置参数:var l_title_popover = typeof title_popover != 'undefined' ? title_popover : ''
。这看起来很糟糕而且令人困惑。 - 使用像
view.title_popover = typeof title_popover != 'undefined' ? title_popover : ''
这样的命名空间。我希望我的变量是局部变量,而不是全局变量,如果我这样做,我将拥有一些全局变量,它会一直存在于内存中。
你会如何处理?我很好奇,也许有一些 EJS 方法可以处理这个问题或帮助程序,我不知道。
有filters in ejs. Also see adding-filters的概念。
基本上我认为您正在寻找与此类似的东西。如果 res.locals 中存在,下面的代码将设置 title_popover,否则设置为 'some default value'
<%=: locals | get:'title_popover','some default value' %>
ejs.filters.get = function(obj, prop, default) {
return obj[prop] === undefined ? default : obj[prop];
};
我相信这是在 ejs 中最简单的方法,但可能还有一些其他方法。看起来像 this actually being discussed on a github ticket :)
编辑 - This blog post 似乎提供了一些使用下划线库的替代方案。看起来他们以某种方式将模板包装在布局中(我还没有完全理解这篇文章,但从表面上看似乎很有意义)。
不过我只用过上面的方法
EJS 不是一个好的模板,这是可以预料的,因为它非常古老且不活跃。也就是说,在传递变量时,JS 的模板引擎并不完全 well-featured。我正在使用 Sails 框架,我所做的只是将变量传递到我的路由设置(如果它们是硬编码的)或我的控制器(如果它们是动态的)中的视图。
也可以通过策略向 res.locals
提供标准路由设置。
例如,我在航行路线中有以下设置:
'GET /':{
controller: 'IndexController.js',
action: 'displayIndexPage',
title: 'Main page',
},
'GET /flowchart': {
controller: 'FlowchartController.js',
action: 'displayFlowchart',
title: 'Flowchart'
}, //...
然后我有一个策略viewToLocals.js
,代码如下:
module.exports = function(req, res, next) {
res.locals.view = req.options.title;
return next();
};
顺便说一句,这不会覆盖我从控制器或任何其他文件传递给视图的任何数据。如果我遇到你的问题,我能做的是这样的:
//setPageParamsPolicy.js
module.exports = function(req, res, next) {
res.locals.popovers = {
title: ('undefined') ? res.get('body').username : 'Default title', //or wherever you fetch data from
icon : ('undefined') ? res.get('body').avatar : 'www.site.com/defaultAvatar.jpg'
}
return next();
};
Sails 是基于 Express 构建的,因此这些信息可能会有用。但是请注意,帆策略适用于控制器操作,这意味着如果您定义一个简单的视图视图,它不会应用 - 您必须将它路由到特定的控制器。但是,您可以将此 object 放入路由中:
//routes.js
'GET /userpanel': {
view: 'userpanel',
locals = {
popover: {
title: ('undefined') ? res.get('body').username : 'Default title', //or wherever you fetch data from
icon : ('undefined') ? res.get('body').avatar : 'www.site.com/defaultAvatar.jpg'
}
}
}
我也对此感到疑惑,并得出结论,没有简单的方法可以做到这一点。但对我来说,Sails 提供了一个相对简单的解决方案,同时也相对简单易行。
如果您喜欢使用纯 JS 来处理事物,EJS 是一种出色的模板语言。该项目目前非常活跃。
NPM 上的 EJS 模块(现在是 v2)在这里积极维护:https://github.com/mde/ejs。 (不再维护旧的 v1 存储库。)
着陆点在这里:http://ejs.co
不应在模板中设置数据的默认值。模板应该只用于渲染。更好的方法是在传入数据之前对其进行预处理:
var defaultVals = {
foo: 'FOO',
bar: 'BAR'
};
// Mix in left to right: https://gist.github.com/mde/81b131ff6810ed7c4e0e
var dataObj = mixin({}, defaultVals, {bar: 'NOT BAR'});
// Outputs "FOO, NOT BAR"
ejs.render('<%= [foo, bar].join(", "); %>', dataObj);
顺便说一下,在 v2 中从 EJS 中删除了过滤器。它们是与嵌入式无关的非标准功能 JavaScript,并且很容易使用您自己的代码进行复制。
我在 ejs 中这样定义默认变量:
<% var username, password%>
<script>
var username = "<%= username %>",password = "<%= password %>" %>
</script>