<%标签中的Interweave EJS和Javascript变量 [英] Interweave EJS and Javascript variables inside <% tags

查看:165
本文介绍了<%标签中的Interweave EJS和Javascript变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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



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

解决方案

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



可以获得更多的数据到模板中并重新渲染它,而不是以你想的方式,而不是向服务器发出另一个请求(除非是获得更多的数据,不要获得更多的HTML)。



解决方案:



很难回答没有更多的细节,所以我要做一些假设,为什么你想传递一个选定的值到EJS模板。我将尽力回答有关您的目标的有限信息。



看起来您的用户正在页面上执行某些操作,例如选择清洁供应,并且您要根据用户选择的元素不同地渲染数据。为此,您可以重新渲染模板并传递用于标识选择哪个元素的数据,使用视图帮助程序将特定类应用于所选元素:



这是修改的clean.ejs模板,使用view helper添加类:



clean.ejs:

 < script> 
//注意:即使取消注释,模板中的JavaScript也不会运行。
// var selected = 1;
< / script>
< h1><%= title%>< / h1>
< ul> (var i = 0; i< supplies.length; i ++){%>
<

< li>
<! - 将类应用于所选元素 - >
< a class ='<%= supplies [i] .selected%>'href ='supplies /<%= supplies [i] .value%>'>
<%= supplies [i] .value%>
< / a>
< / li>
<%}%>
< / ul>

呈现的HTML格式如下:

 < script> 
/ **注意:脚本块不会在渲染的模板中触发。忽略它们
// var selected = 1;
< / script>
< h1>清洁用品< / h1>
< ul>


< li>
< a class =href =supplies / Broom>
Broom
< / a>
< / li>


< li>
<! - 注意所选元素 - >
< a class =selectedhref =supplies / mop>
mop
< / a>
< / li>


< li>
< a class =href =supplies / Hammer>
Hammer
< / a>
< / li>

< / ul>

此视图使用以下JavaScript代码呈现:

  //修改后的数据结构,以便数组的资源包含对象
//与项目的名称以及是否选择。
data = {
title:清洁用品,
耗材:[
{
value:Broom,
selected:
},
{
value:mop,
selected:selected
},
{
value:Hammer,
selected:
}
]
};

//将数据传递给模板并呈现
var html = new EJS({url:'cleaning.ejs'})。render(data);

//使用< div id =container>< / div>向HTML添加HTML包装。
document.getElementById(container)。innerHTML = html;

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



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



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

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






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



您尝试用来操作JavaScript值或在EJS模板中使用JavaScript值的方法将无法正常工作。当执行JavaScript时,这主要需要执行的上下文。



您可以认为EJS模板是在客户端。但是,视图助手中的JavaScript是独立于全局上下文中的JavaScript执行的。从查看ejs.js源代码来看,似乎在进程中使用了eval。



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

  document.getElementById(container)。innerHTML = html; 

无论您使用什么视图技术,某些浏览器的基本原理之一就是对于JavaScript是这样的:某些浏览器可能无法评估使用innerHTML添加到DOM中的< script> 块。


换句话说,在我的测试模板中,当我尝试添加一个脚本标签以将选定的值输出到控制台时,我可以看到脚本块被添加,但是由于innerHTML的工作原理,没有执行:



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

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

呈现HTML:



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



使用视图技术的方法是限制其使用,从而渲染视图。 将您的逻辑保留在常规JavaScript中。

 < h1>清洁用品< / 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>

更多示例和文档可以在EJB模板上找到 Google Code Embedded JavaScript 网站。


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

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?

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.

解决方案

Can I pass a JavaScript variable into a template?:

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).

Solution:

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

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:

<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:

<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:

// 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.

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

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

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


Why JavaScript in the template doesn't run:

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 when the JavaScript is executed.

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.

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:

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.

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:

Example Template Demonstrates JavaScript won't run if added using innerHTML:

 <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:

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

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".

<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 JavaScript site.

这篇关于&lt;%标签中的Interweave EJS和Javascript变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆