我有这个EJS模板代表我的Web应用程序的标题。我试图访问我在前端Backbone应用程序中定义的全局变量,但由于某种原因,我收到一条错误,说“appGlobal未定义”。我的前端JavaScript中的全局变量如下:
appGlobal = {
authorized: null,
currentUser: null,
env: null
};
模板如下所示:
<header>
<div>
<div id="header-div-id">
<% if(appGlobal && appGlobal.currentUser != null) { %>
<div>Logged In As: <%= appGlobal.currentUser%></div>
<button id="logout-button-id">Logout</button>
<% } else { %>
<div>You need to either register or login.</div>
<% } %>
</div>
</div>
</header>
所以看起来确实模板是在服务器端呈现的 - 移动它以使其呈现客户端的最佳方式是什么?标头模板包含在index.ejs文件中,如下所示:
<% include ./partials/header %>
<main>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
<div name="main-div" id="main-div-id">
</div>
</main>
<% include ./partials/footer %>
答案 0 :(得分:3)
您正在使用的模板系统(EJS)在服务器端执行,并且不知道与客户端代码相关的语义。
在这种情况下,appGlobal
变量声明永远不会被EJS
评估,因此无法通过服务器端作用域访问。
答案 1 :(得分:1)
- 我认为appGlobal未在模板中定义的原因 是因为模板是服务器端而不是客户端;和appGlobal是一个全球化的客户。
醇>
这完全正确;您发送到浏览器的任何代码(HTML,CSS,JS)都不会被服务器以任何方式解析:服务器将该代码视为文本。在编译服务器端模板时,尚未在浏览器中运行的任何JavaScript都已运行。
- 但是,此代码仍应检查appGlobal是否已定义,因此我不明白它为什么会抛出错误???
醇>
嗯,确实如此,但appGlobal
未在服务器上定义,因为代码不在服务器上运行。它只在客户端上运行。
- 如果我更改模板以使用window.appGlobal,则不定义窗口
醇>
由于同样的原因,没有定义。
一种可能的解决方案是为了在服务器上安装appGlobal
变量,然后使用EJS将其添加到客户端代码中。例如,在服务器代码中的某个位置,您可能有类似这样的内容:
ejs.render(templateStr, { data: 'here' });
(如果您使用像Express这样的库,可能会有点不同。)
如果您在服务器上创建appGlobal
,则可以将其作为参数添加到数据对象中,并在模板中根据需要使用它:
var appGlobal = {
authorized: null,
currentUser: null,
env: null
};
ejs.render(templateStr, { appGlobal: appGlobal });
但是,如果您想在客户端提供此变量,您可以对其进行字符串化并将其添加到模板中。所以JavaScript看起来像这样:
ejs.render(templateStr, {
appGlobal: appGlobal,
appGlobalStr: JSON.stringify(appGlobal)
});
然后在您的模板中,您可以执行以下操作:
<script>
var appGlobal = <%- appGlobalStr %>;
</script>
注意使用<%- %>
分隔符,用于非转义输出。
实现非常重要,这意味着客户端最初会获得服务器appGlobal
变量的当前值,但不会保留#&strong# 34;同步&#34;一点都不此外,请确保客户端可以访问appGlobal
对象的所有属性。例如,如果您使用用户记录执行此类操作,则您绝对不希望将passwordHash
(以及许多其他属性)发送到客户端。