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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10777246/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 02:52:47  来源:igfitidea点击:

Interweave EJS and Javascript variables inside <% tags

javascriptnode.jsexpressejs

提问by philipDS

I need to use a Javascript variable (defined in the front-end) in some EJS code, as follows:

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

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

I'm using EJS, Express.js and socket.io. I could convert the Javascript variable to an EJS variable by sending a message to my Node.js server instance, but that's kind of silly... Is there a way to use Javascript variables inside EJS?

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

EDIT: I want to access supplies, a javascript array, after the user selected an item from a drop down menu. When he selects this item, a javascript function with the above code needs to access some EJS. That's why I need to use a normal Javascript variable in EJS.

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

回答by jmort253

Can I pass a JavaScript variable into a template?:

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

It is possible to get more data into the template and re-render it, but not in the manner that you're thinking, and without making another request to the server (unless it's to get more data, not to get more HTML).

可以将更多数据放入模板并重新渲染它,但不是以您所想的方式,并且无需向服务器发出另一个请求(除非它是为了获取更多数据,而不是获取更多 HTML)。

Solution:

解决方案:

This question is going to be difficult to answer without more details, so I'm going to make some assumptions about whyyou want to pass a selected value into an EJS template. I'll do my best to answer this with limited information about your goals.

如果没有更多细节,这个问题将很难回答,因此我将就为什么要将选定的值传递到 EJS 模板做出一些假设。我会尽我所能用关于你的目标的有限信息来回答这个问题。

It seems like your user is performing some action on the page, like selecting a cleaning supply, and you want to render the data differently, based on which element the user selected. To do this, you can re-render the template and pass in data that identifies which element is selected, using a view helper to apply a specific class to the selected element:

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

Here is the modified cleaning.ejs template, with the class added using the view helper:

这是修改后的cleaning.ejs 模板,使用视图助手添加了类:

cleaning.ejs:

清洁.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>    

The rendered HTML looks like this:

呈现的 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>

This view was rendered using the following JavaScript code:

此视图是使用以下 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;

As you can see, supplies[i].selected applies the selected class to the element that was marked as selected in the data structure. I modified the href value so that it accessed the object in the ith array item instead of the value of the array itself.

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

Now, when the selected item is modified, we simply modify the data variable, re-render the EJS template, and add it to the DOM.

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

With this CSS in the head of your HTML document, you'll see something similar to what's displayed below:

在 HTML 文档的头部使用此 CSS,您将看到类似于下面显示的内容:

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

Demo of selected element in red

红色选定元素的演示



Why JavaScript in the template doesn't run:

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

The method that you're attempting to use to manipulate JavaScript values or use JavaScript values inside the EJS template won't work. This has to do mainly with the context of whenthe JavaScript is executed.

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

You're right to think that the EJS templates are compiled on the client-side. However, the JavaScript in the view helpers are executed independent of the JavaScript in the Global context. From looking at the ejs.js source code, it appears as if eval is used in the process.

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

Additionally, EJS returns the rendered HTML as a string, and the documentation for EJS instructs us to inject that rendered template string into the DOM using innerHTML:

此外,EJS 将渲染的 HTML 作为字符串返回,并且 EJS 的文档指示我们使用 innerHTML 将渲染的模板字符串注入到 DOM 中:

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

No matter what view technology you're using, one of the fundamental truths of some browsers when it comes to JavaScript is this: Some browsers may not evaluate <script>blocks added to the DOM using innerHTML.

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

In other words, in my test template, when I tried adding a script tag to output the selected value to the console, I could see that the script block was added, but due to the way innerHTML works, it was not executed:

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

Example Template Demonstrates JavaScript won't run if added using 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>

Rendered HTML:

渲染的 HTML:

As you can see below, the console.log statements are present in the HTML. However, when added using innerHTML, they will not fire.

正如您在下面看到的,console.log 语句存在于 HTML 中。但是,当使用innerHTML 添加时,它们不会触发。

The approach to take with view technologies is to limit their use to just that, rendering the view.Keep your logic in the "regular JavaScript".

使用视图技术的方法是将它们的使用限制为渲染视图。将您的逻辑保留在“常规 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>

More examples and documentation can be found on EJS Templates on the Google Code Embedded JavaScriptsite.

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