与EJS斗争,范围为-not so-" local"变量

时间:2015-03-21 22:08:37

标签: javascript node.js scope ejs

我想知道如何使用EJS模板编写我的node.js应用程序。 我实际上正在寻找一种在部分/模板中使用默认值定义局部变量的正确方法。

我很快就会发现它现在有效:

当我调用模板时,像这样:

<%- partial(__view.partialPath('tagPopover'), {
    title_popover: sentence.nickname,
    content_tag: '#' + sentence.nickname,
    icon_popover: 'http://placehold.it/64x64'
}) %>

我在_tagPopover.ejs partial:

中以这种方式管理默认值
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!这意味着它是一个非常糟糕的解决方案,因为我可能最终通过加载视图来重写全局变量!

我相信这将是一个艰难的过程,我不希望我的观点默认设置/重置全局变量(谁会?!)

你有什么解决方案吗?我已经考虑了几个,但我不喜欢任何:

  1. 使用var关键字,但也可以使用模式 之前的局部变量来避免重置参数:var l_title_popover = typeof title_popover != 'undefined' ? title_popover : ''。这看起来很糟糕,令人困惑。
  2. 使用view.title_popover = typeof title_popover != 'undefined' ? title_popover : ''之类的命名空间。我希望我的变量是本地变量,而不是全局变量,如果我这样做,我将会有一些全局存在于内存中的东西。
  3. 你会怎么处理?我很好奇,也许有一些EJS方式来处理它或帮助,我不知道。

4 个答案:

答案 0 :(得分:2)

ejs中有filters的概念。另请参阅adding-filters

基本上我认为你正在寻找类似的东西。如果存在于res.locals中,下面的代码将设置title_popover,否则它设置为'某个默认值'

<%=: 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似乎使用下划线库提供了一些替代方案。看起来他们正在以某种方式将模板包装在一个布局中(我还没有完全理解这篇文章,但它似乎在表面上有意义。)

然而,我只使用了上述方式。

答案 1 :(得分:0)

EJS不是一个好的模板,因为它很老而且不活跃。也就是说,JS的模板引擎在传递变量方面并不是那么精彩。我正在使用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构建的,所以这些信息可能会有用。但是请注意,sails策略适用于控制器操作,这意味着如果您定义一个简单的路径来查看,它就不会应用 - 您必须将其路由到特定的控制器。但是,您可以将此对象放入其中的路径:

//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提供了一个相对简单的解决方案,也是相对简单的。

答案 2 :(得分:0)

如果你喜欢使用普通的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无关,并且易于使用您自己的代码进行复制。

答案 3 :(得分:0)

我在ejs中定义了这样的默认变量:

<%  var username, password%>
<script>
    var username = "<%= username %>",password = "<%= password %>" %>
</script>