在<%标记内交织EJS和Javascript变量

phi*_*pDS 15 javascript ejs node.js express

我需要在一些EJS代码中使用Javascript变量(在前端定义),如下所示:

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

我正在使用EJS,Express.js和socket.io.我可以通过向我的Node.js服务器实例发送消息将Javascript变量转换为EJS变量,但这有点傻......有没有办法在EJS中使用Javascript变量?

编辑:我想在用户从下拉菜单中选择一个项目后访问耗材,一个javascript数组.当他选择这个项目时,带有上述代码的javascript函数需要访问一些EJS.这就是我需要在EJS中使用普通Javascript变量的原因.

jmo*_*253 46

我可以将JavaScript变量传递给模板吗?:

可以将更多数据添加到模板中并重新呈现它,但不是以您正在考虑的方式,而不是向服务器发出另一个请求(除非是为了获取更多数据,而不是获取更多HTML).

解:

如果没有更多细节,这个问题将难以回答,因此我将对您为什么要将选定值传递给EJS模板做出一些假设.我会尽力回答有关您目标的有限信息.

您的用户似乎正在页面上执行某些操作,例如选择清洁耗材,并且您希望根据用户选择的元素以不同方式呈现数据.为此,您可以重新呈现模板并传入标识所选元素的数据,使用视图助手将特定类应用于所选元素:

这是修改后的cleaning.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>    
Run Code Online (Sandbox Code Playgroud)

呈现的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>
Run Code Online (Sandbox Code Playgroud)

此视图使用以下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;
Run Code Online (Sandbox Code Playgroud)

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

现在,当修改所选项时,我们只需修改数据变量,重新渲染EJS模板,然后将其添加到DOM.

将这个CSS放在HTML文档的头部,你会看到类似于下面显示的内容:

<style>
    .selected { color:red; }
</style>
Run Code Online (Sandbox Code Playgroud)

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


为什么模板中的JavaScript无法运行:

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

您认为EJS模板是在客户端编译的,这是正确的.但是,视图助手中的JavaScript独立于Global上下文中的JavaScript而执行.从查看ejs.js源代码看,好像在进程中使用了eval.

另外,EJS将呈现的HTML作为字符串返回,EJS的文档指示我们使用innerHTML将呈现的模板字符串注入DOM:

document.getElementById("container").innerHTML = html;
Run Code Online (Sandbox Code Playgroud)

无论您使用何种视图技术,一些浏览器在JavaScript方面的基本事实之一是: 某些浏览器可能无法<script>使用innerHTML 评估添加到DOM的块.

换句话说,在我的测试模板中,当我尝试添加脚本标记以将所选值输出到控制台时,我可以看到添加了脚本块,但由于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>
Run Code Online (Sandbox Code Playgroud)

呈现的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>
Run Code Online (Sandbox Code Playgroud)

可以在Google Code Embedded JavaScript站点上的EJS模板上找到更多示例和文档.

  • 神圣......真是个答案!谢谢.这澄清了很多事情!你的解决方案让我走上了正确的道路,我应该把更多的逻辑从EJS中剔除我猜... :) (2认同)