Javascript 如何从EJS模板中获取属性列表?

Javascript 如何从EJS模板中获取属性列表?,javascript,node.js,ejs,Javascript,Node.js,Ejs,我将响应字符串存储在EJS表单中的数据库中,并在节点中填写数据。我想做的是能够使用我想要的任何属性,不管它来自什么模型,然后在节点中,异步/等待这些模型,一旦我有了模板,根据需要的属性 因此,如果我有一个模板,如: "Hello <%=user.firstName%>." 或者类似的 我认为res.locals是您在本例中所要查找的内容 app.set('view engine', 'ejs'); var myUser = { user : { username

我将响应字符串存储在EJS表单中的数据库中,并在节点中填写数据。我想做的是能够使用我想要的任何属性,不管它来自什么模型,然后在节点中,异步/等待这些模型,一旦我有了模板,根据需要的属性

因此,如果我有一个模板,如:

"Hello <%=user.firstName%>."

或者类似的

我认为
res.locals
是您在本例中所要查找的内容

app.set('view engine', 'ejs');
var myUser = {
  user :
    {
    username: 'myUser',
    lastName: 'userLastName',
    location: 'USA'
  }
}

app.use(function(req, res, next){
  res.locals = myUser;
  next();
})

app.get('/', function(req, res){
  res.render('file.ejs');
})
在任何ejs文件中,我们都可以随意使用属性

  <body>
    <h3>The User</h3>
    <p><%=user.username%></p>
    <p><%=user.lastName%></p>
    <p><%=user.location%></p>
  </body>

用户


不幸的是,EJS不提供从模板解析和提取变量名的功能。它有
compile
方法,但此方法返回一个可用于按模板呈现字符串的值。但是你需要得到一些中间结果,来提取变量

你可以用电脑来做

胡须默认分隔符是
{}
。你可以替换它们。不幸的是,Mustach不允许定义多个分隔符(例如,
),所以如果您试图编译包含多个分隔符的模板,Mustach将抛出一个错误。可能的解决方案是创建一个函数,该函数接受模板和分隔符,并将所有其他delimeter替换为中性的。并为每对分隔符调用此函数:

let vars = [];
vars.concat(parseTemplate(template, ['<%', '%>']));
vars.concat(parseTemplate(template, ['<%=', '%>']));
...
let uniqVars = _.uniq(vars);
let _        = require('lodash');
let Mustache = require('Mustache');

let template = 'Hello <%= user.firstName %> <%= user.lastName %> <%= date %>';
let customTags = ['<%=', '%>'];

let tokens = Mustache.parse(template, customTags);
let vars = _.chain(tokens)
  .filter(token => token[0] === 'name')
  .map(token => {
    let v = token[1].split('.');
    return v;
  })
  .flatten()
  .uniq()
  .value();

console.log(vars); // prints ['user', 'firstName', 'lastName', 'date']
let vars=[];
变量concat(parseTemplate(模板,['']);
变量concat(parseTemplate(模板,['']);
...
设uniqVars=uq.uniq(vars);
下面是仅适用于一对分隔符的简单变量:

let vars = [];
vars.concat(parseTemplate(template, ['<%', '%>']));
vars.concat(parseTemplate(template, ['<%=', '%>']));
...
let uniqVars = _.uniq(vars);
let _        = require('lodash');
let Mustache = require('Mustache');

let template = 'Hello <%= user.firstName %> <%= user.lastName %> <%= date %>';
let customTags = ['<%=', '%>'];

let tokens = Mustache.parse(template, customTags);
let vars = _.chain(tokens)
  .filter(token => token[0] === 'name')
  .map(token => {
    let v = token[1].split('.');
    return v;
  })
  .flatten()
  .uniq()
  .value();

console.log(vars); // prints ['user', 'firstName', 'lastName', 'date']
let=require('lodash');
let Mustache=需要('Mustache');
让template='Hello';
让customTags=[''];
让tokens=Mustache.parse(模板,customTags);
设vars=u.chain(令牌)
.filter(令牌=>令牌[0]==“名称”)
.map(令牌=>{
设v=token[1]。拆分('.');
返回v;
})
.flatte()
.uniq()
.value();
console.log(vars);//打印['user','firstName','lastName','date']

如果您只想提取一些简单的东西,比如
user.firstName
,那么在EJS文件上运行RegExp可能是一种很好的方法。很有可能你会寻找一组特定的已知对象和属性,这样你就可以专门针对它们,而不是试图提取所有可能的对象/属性

在更一般的情况下,事情很快就会变得困难。这样的事情很难处理:

<% var u = user; %><%= u.firstName %>
在这种情况下,
用户
直接来自
本地人
,但
用户
不是。要解决这个问题,我们需要类似于IDE中的变量范围分析

下面是我试过的:

  • 将模板编译为JS
  • 使用将JS解析为AST
  • 遍历AST以查找所有标识符。如果它们看起来是全球性的,就会被退回。这里的“全局”是指真正的全局或它们是
    locals
    对象中的一个条目。EJS在内部使用
    和(局部变量){…}
    ,因此实际上无法知道它是哪一个
  • 我想像力地调用了结果
    ejsprima

    我还没有尝试支持EJS支持的所有选项,因此如果使用自定义分隔符或严格模式,它将无法工作。(如果您使用的是严格模式,您必须在模板中显式地写入
    locals.user.firstName
    ,这需要通过RegExp来实现)。它不会尝试跟随任何
    include
    调用

    如果没有bug潜伏在某处,我会非常惊讶,即使是一些基本的JS语法,但我已经测试了我能想到的所有恶劣情况。包括测试用例

    主演示中使用的EJ可以在HTML的顶部找到。我已经包括了一个免费的“全球写作”的例子,只是为了展示它们的样子,但我认为它们不是你通常想要的东西。有趣的是
    读取部分

    我针对esprima 4开发了这个,但我能找到的最好的CDN版本是2.7.3。所有的测试都通过了,所以这似乎不太重要

    我在代码片段的JS部分中包含的唯一代码是针对“ejsprima”本身的。要在节点中运行该功能,您只需将其复制并调整顶部和底部,以更正导出和所需内容

    //开始“ejsprima”
    (职能(出口){
    //var esprima=需要('esprima');
    //简单的EJS编译器,丢弃HTML部分,只保留JavaScript代码
    exports.compile=函数(tpl){
    //提取标签
    var tags=tpl.match(/()/g);
    返回标签.map(函数(标签){
    var parse=tag.match(/^()$/);
    开关(解析[1]){
    案例“”,[a',c']);
    资产价值('b+c;'b+=6;%>'、['a','b','c']、['b']);
    资产价值(“”,['c']);
    资产价值(“”,['c']);
    资产价值('',['c','d']);
    资产价值('',['c','d']);
    资产价值('',['c','d','e']);
    资产价值(“”,['c','d','e','g'],['f']);
    资产价值(“”,['c'],['a']);
    资产价值('',['c','d']);
    资产价值('',['a','c','d']);
    资产价值(“”,[]);
    资产价值(“”,['b']);
    资产价值('',['a','c','d']);
    资产价值(“”,['b']);
    资产价值(“”,['b']);
    资产价值(“”,['b'],['a']);
    资产价值(“”,['b'],['a']);
    资产价值(“”,['b']);
    资产价值(“”,['b','c']);
    资产价值(“”,['c']);
    资产价值(“”,['a'],['a']);
    资产价值(“”,['a']);
    资产价值(“”);
    资产价值(“”,['a'],['a']);
    资产价值(“”);
    资产价值(“”,['a']);
    资产价值(“”,['a']);
    资产价值(“”,['a',b']);
    资产价值('',['a','b','c']);
    资产价值(“”,['a',c']);
    资产价值(“”,['a',b']);
    资产价值(“”,['b']);
    资产价值(“”,['b'