You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

express-ejs-layouts布局使用问题:页面渲染DOM元素获取报错

express-ejs-layouts布局问题解决:页面脚本适配错误

问题场景

我在学习express-ejs-layouts时,尝试用layout.ejs承载公共内容(比如样式、通用脚本),制作了两个页面模板:

  • dashboard.ejs:包含<h1 id="heading"></h1>
  • homepage.ejs:包含<h1 id="heading1"></h1>

layout.ejs代码:

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="css/style.css" type="text/css" />
    </head>
    <body>
        <%- body %>
        <script type="text/javascript">
            document.getElementById("heading").innerHTML = "Hello, There!!";
            document.getElementById("heading1").innerHTML = "Homepage";
        </script>
    </body>
</html>

路由渲染代码:

app.get('/',(req, res)=>{
    res.render('dashboard');
})

app.get('/homepage',(req, res)=>{
    res.render('homepage');
})

访问/路径时页面正常,但访问/homepage时页面无内容,控制台报错:

Uncaught TypeError: Cannot set properties of null (setting 'innerHTML')

原因是渲染homepage时,页面中不存在heading元素,脚本执行到该行直接抛出错误,后续代码也无法执行。

问题分析

你的布局实现逻辑存在错误:公共layout中的脚本同时操作了两个页面独有的DOM元素。express-ejs-layouts的核心是让所有页面共用同一个布局框架,当渲染某一个页面时,只会把该页面的模板内容插入到<%- body %>的位置,其他页面的DOM元素不会存在。此时公共脚本里尝试访问不存在的元素,就会触发null赋值错误,导致脚本中断,页面内容无法正常渲染。

解决方法

方法1:给DOM元素添加存在性判断

修改layout中的脚本,每次获取元素后先判断是否存在,再执行赋值操作:

const heading = document.getElementById("heading");
if (heading) {
  heading.innerHTML = "Hello, There!!";
}

const heading1 = document.getElementById("heading1");
if (heading1) {
  heading1.innerHTML = "Homepage";
}

这种方法适合脚本逻辑简单、必须放在公共layout中的场景。

方法2:页面专属脚本拆分到对应模板

将页面独有的脚本从公共layout中移除,放到各自的EJS模板里,layout只保留全局通用的内容:

  • dashboard.ejs:
<h1 id="heading"></h1>
<script>
  document.getElementById("heading").innerHTML = "Hello, There!!";
</script>
  • homepage.ejs:
<h1 id="heading1"></h1>
<script>
  document.getElementById("heading1").innerHTML = "Homepage";
</script>

layout.ejs简化为:

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="css/style.css" type="text/css" />
    </head>
    <body>
        <%- body %>
        <!-- 这里只放全局通用脚本,比如全局工具类、第三方库引入等 -->
    </body>
</html>

这种方式更符合模块化思想,脚本只在对应的页面执行,避免跨页面的DOM依赖问题。

方法3:通过模板变量直接渲染内容(推荐)

不需要用JS操作DOM,直接在后端渲染时传递页面专属变量,在模板中直接填充内容:
修改路由代码:

app.get('/',(req, res)=>{
    res.render('dashboard', { pageTitle: "Hello, There!!" });
})

app.get('/homepage',(req, res)=>{
    res.render('homepage', { pageTitle: "Homepage" });
})

统一两个模板的h1元素(也可保持不同id但用变量填充):

  • dashboard.ejs:
<h1 id="heading"><%= pageTitle %></h1>
  • homepage.ejs:
<h1 id="heading1"><%= pageTitle %></h1>

这种方式完全避免了前端DOM操作的问题,渲染效率更高,也更符合EJS模板的使用逻辑。

内容的提问来源于stack exchange,提问作者Kanojian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 09:05:22