在<%标签内交织EJS和Javascriptvariables

我需要在EJS代码中使用一个Javascriptvariables(在前端定义),如下所示:

var selected = 1; <% for (var i=0; i < supplies.length; i++) { %> if (i == selected) { console.log(supplies); } <% } %> 

我正在使用EJS,Express.js和socket.io。 我可以通过向我的Node.js服务器实例发送一个消息来将JavaScriptvariables转换为EJSvariables,但这是一种愚蠢的…有没有一种方法可以在EJS内使用Javascriptvariables?

编辑:我想访问用品,一个JavaScript数组,在用户从下拉菜单中select一个项目后。 当他select这个项目时,具有上述代码的JavaScript函数需要访问一些EJS。 这就是为什么我需要在EJS中使用正常的Javascriptvariables。

我可以将JavaScriptvariables传递给模板吗?

可以将更多的数据添加到模板中并重新渲染,而不是以您想的方式进行渲染,也不需要向服务器发出另一个请求(除非获得更多的数据,不要获取更多的HTML)。

解:

如果没有更多的细节,这个问题将会很难回答,所以我要对你为什么要将选定的值传递给EJS模板做一些假设。 我会尽全力用有限的信息来回答你的目标。

看起来你的用户正在页面上执行一些操作,比如select一个清理工具,并且你想要根据用户select的元素以不同的方式渲染数据。 要做到这一点,你可以重新渲染模板,并传递数据来标识哪个元素被选中,使用视图帮助器将特定的类应用到选定的元素:

这里是修改后的clean.ejs模板,使用视图帮助器添加类:

cleaning.ejs:

 <script> // NOTE: even if uncommented, JavaScript inside a template will not run. // var selected = 1; </script> <h1><%= title %></h1> <ul> <% for(var i=0; i<supplies.length; i++) { %> <li> <!-- apply a class to the selected element --> <a class='<%= supplies[i].selected %>' href='supplies/<%= supplies[i].value %>'> <%= supplies[i].value %> </a> </li> <% } %> </ul> 

呈现的HTML如下所示:

 <script> /** NOTE: Script blocks will not fire in rendered templates. They are ignored // var selected = 1; </script> <h1>Cleaning Supplies</h1> <ul> <li> <a class="" href="supplies/Broom"> Broom </a> </li> <li> <!-- Note the selected element --> <a class="selected" href="supplies/mop"> mop </a> </li> <li> <a class="" href="supplies/Hammer"> Hammer </a> </li> </ul> 

该视图使用以下JavaScript代码进行呈现:

 // modified data structure so that array of supplies contains objects // with the name of the item and whether or not it's selected. data = { "title":"Cleaning Supplies", "supplies":[ { "value":"Broom", "selected":"" }, { "value":"mop", "selected":"selected" }, { "value":"Hammer", "selected":"" } ] }; // pass data into template and render var html = new EJS({url: 'cleaning.ejs'}).render(data); // add HTML to the DOM using a <div id="container"></div> wrapper. document.getElementById("container").innerHTML = html; 

如您所见,耗材[i] .selected将选定的类应用于在数据结构中标记为选中的元素。 我修改了href值,以便它访问第i个数组项中的对象,而不是数组本身的值。

现在,当select的项目被修改时,我们只需修改数据variables,重新渲染EJS模板,并将其添加到DOM。

将这个CSS放在HTML文档的头部,您将看到类似于以下内容的内容:

 <style> .selected { color:red; } </style> 

所选元素的演示以红色显示


为什么模板中的JavaScript不运行:

您试图用来操纵JavaScript值或在EJS模板中使用JavaScript值的方法将不起作用。 这主要与JavaScript执行的上下文有关。

您正确地认为EJS模板是在客户端编译的。 但是,视图帮助器中的JavaScript独立于全局上下文中的JavaScript执行。 从查看ejs.js源代码,看起来好像在过程中使用了eval。

此外,EJS将呈现的HTML作为string返回,EJS的文档指示我们使用innerHTML将呈现的模板string注入到DOM中:

 document.getElementById("container").innerHTML = html; 

无论您使用哪种视图技术,某些浏览器在JavaScript中的基本真理之一是: 某些浏览器可能不会评估使用innerHTML添加到DOM的<script>块。

换句话说,在我的testing模板中,当我尝试添加脚本标记以将所选值输出到控制台时,我可以看到添加了脚本块,但是由于innerHTML的工作方式,它没有执行:

示例模板演示如果使用innerHTML添加,JavaScript将不会运行:

  <h1><%= title %></h1> <ul> <% for(var i=0; i<supplies.length; i++) { %> <span id="selected"></span><script>console.info('test <%= i %> = <%= supplies[i] %>');</script> <li> <a href='supplies/<%= supplies[i] %>'> <%= supplies[i] %> </a> </li> <% } %> </ul> 

呈现HTML:

如下所示,console.log语句存在于HTML中。 但是,使用innerHTML添加时,它们不会触发。

采用视图技术的方法是限制它们的使用,使视图呈现。 保持你的逻辑在“普通的JavaScript”。

 <h1>Cleaning Supplies</h1> <ul> <span id="selected"></span><script>console.info('test 0 = Brrom');</script> <li> <a href='supplies/Brrom'> Brrom </a> </li> <span id="selected"></span><script>console.info('test 1 = mop');</script> <li> <a href='supplies/mop'> mop </a> </li> <span id="selected"></span><script>console.info('test 2 = Hammer');</script> <li> <a href='supplies/Hammer'> Hammer </a> </li> </ul> 

更多示例和文档可以在Google Codeembedded式JavaScript网站的EJS模板上find。