简体   繁体   English

如何在 EJS 模板中运行 JS 函数 - Express、EJS 和 UIkit

[英]How to run JS function in EJS template - Express, EJS and UIkit

I get UIkit is not defined though the JS is loaded in the header.我得到UIkit is not defined ,尽管 JS 已加载到标题中。 Even alert doesn't work.即使alert也不起作用。 How to solve this?如何解决这个问题?

EJS index template- EJS 索引模板-

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/uikit.min.css" />
    <script src="js/uikit.min.js"></script>
    <script src="js/uikit-icons.min.js"></script>
    <title>Site</title>

</head>

<body>

    <% if (message) {%>
        <%= UIkit.notification(message) %>
    <% }; %>

</body>
</html>

Express app JS快递应用JS

var message = 'Error - not found';
//routes
app.get('/', (request, response) => {
response.render('index', {message: message});
}

Error错误

    17|     <% if (message) {%>

 >> 18|         <%= UIkit.notification(message) %>

    19|     <% }; %>

    20|             <div class="uk-width-1-1">


UIkit is not defined

Error on trying alert尝试警报时出错

    17|     <% if (message) {%>

 >> 18|         <%= alert('test') %>

    19|     <% }; %>
   
    20|             <div class="uk-width-1-1">


alert is not defined

There seems to be some confusion about which code runs on the server and which code runs on the client.关于哪些代码在服务器上运行以及哪些代码在客户端上运行似乎有些混淆。

In your setup, EJS is running on the Node server and building a string of HTML that's eventually sent to the client where it's executed in the client's browser.在您的设置中,EJS 在 Node 服务器上运行并构建一个 HTML 字符串,该字符串最终发送到客户端,并在客户端的浏览器中执行。 The EJS <%= ... > syntax lets you evaluate a JS expression in Node context on the server, not in the browser, letting you inject dynamic content into the HTML string. EJS <%= ... >语法允许您在服务器上的 Node 上下文中评估 JS 表达式,而不是在浏览器中,让您将动态内容注入 HTML 字符串。

Here, <%= alert() => says "call Node's alert function on the server and inject the return value into the template".这里, <%= alert() =>表示“在服务器上调用 Node 的alert函数并将返回值注入到模板中”。 But that makes no sense--Node has no such alert() function, nor does it have access to anything that might have been included in a <script> .但这没有任何意义——Node 没有这样的alert()函数,也无法访问可能包含在<script>中的任何内容。 All of that stuff won't be available until long after EJS has finished building the HTML string and sent it to the client.直到 EJS 完成构建 HTML 字符串并将其发送到客户端很久之后,所有这些东西才会可用。

Probably what you're trying to do is inject the string that represents the function you want to call into the template:可能您想要做的是将代表您要调用的函数的字符串注入模板:

 eval(ejs.render(`<%= "alert(42)" %>`));
 <script src="https://unpkg.com/ejs@3.1.6/ejs.min.js"></script>

Rather than the failing code:而不是失败的代码:

 window.alert = undefined; // simulate Node, which has no alert() console.log(ejs.render(`<%= alert(42) %>`)); // fail, trying to call undef func
 <script src="https://unpkg.com/ejs@3.1.6/ejs.min.js"></script>

In the top example, the string "alert(42)" is injected into the template and sent to the "client", where eval() invokes it, roughly simulating how your script will ultimately be evaluated.在上面的示例中,字符串"alert(42)"被注入模板并发送到“客户端”, eval()调用它,大致模拟最终将如何评估您的脚本。

At any rate, there's probably a better way to achieve this result of conditionally setting up a function call, but getting clear on the concept is 99% of the battle.无论如何,可能有更好的方法来实现有条件地设置函数调用的结果,但是弄清楚这个概念是 99% 的战斗。

For example, syntax like this is possible as well:例如,这样的语法也是可能的:

 const template = ` <% if (message) {%> alert("<%= message %>") <% }; %> `; eval(ejs.render(template, {message: "hey"}));
 <script src="https://unpkg.com/ejs@3.1.6/ejs.min.js"></script>

Pop quiz: if you replace alert("<%= message %>") with alert(message) in the above code, will it work?小测验:如果在上面的代码中将alert("<%= message %>")替换为alert(message)会起作用吗? Why or why not?为什么或者为什么不? Try it and see.试试看。

If you can answer this question, you probably understand the difference between evaluating something while EJS runs versus evaluating EJS' output.如果您能回答这个问题,您可能会理解在 EJS 运行时评估某物与评估 EJS 输出之间的区别。

Note: eval is used purely for convenience/pedagogical purposes only here to simulate the client evaluating the HTML script;注意: eval仅用于方便/教学目的,仅用于模拟客户端评估 HTML 脚本; I'm not advocating using it in a real app!我不提倡在真正的应用程序中使用它!

I am assuming you have already installed EJS with npm install ejs .我假设您已经使用npm install ejs安装了 EJS。

Make sure you have the following middleware in your express app (I always missed this middleware as a beginner):确保您的 express 应用程序中有以下中间件(作为初学者,我总是错过这个中间件):

app.set("view engine", "ejs");

As far as alert() is concerned, as others have pointed out, alert() won't work as you run it on the server.就 alert() 而言,正如其他人所指出的那样,当您在服务器上运行它时,alert() 将不起作用。 EJS gets converted to HTML via its engine before it is rendered on the client side. EJS 在客户端呈现之前通过其引擎转换为 HTML。

使用<body onload="UIkit.notification({message:'<%=message%>'})">解决了它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM