Nodejs express局部渲染
Nodejs express局部渲染
我们一般吧header footer都包起来,index.ejs里面会有 <%include header.ejs %> 直接引入 如果header里面有需要数据库的数据渲染 每次app.get(’/’, routes.index);或者其他页面都需要 res.render(‘index’,{‘header’ : results,‘nav’ : results2}); 重复每次读取header里面的数据 这个怎么能解决?能不能分开?
当然可以解决这个问题。在使用 Express 和 EJS 模板引擎时,我们可以利用局部模板(partial templates)来避免重复渲染相同的头部或尾部内容。局部模板允许我们在多个视图中重用相同的 HTML 片段,这样就可以减少代码冗余并提高效率。
示例代码
假设我们有以下目录结构:
/views
/partials
header.ejs
footer.ejs
index.ejs
/routes
index.js
views/partials/header.ejs
<header>
<h1>Welcome to My Website</h1>
<% if (user) { %>
<p>Hello, <%= user.name %>!</p>
<% } else { %>
<p>Please log in.</p>
<% } %>
</header>
views/index.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
<!-- 引入局部模板 -->
<%- include('partials/header'); %>
<main>
<h2>Welcome to the Home Page</h2>
<!-- 其他页面内容 -->
</main>
<!-- 引入局部模板 -->
<%- include('partials/footer'); %>
</body>
</html>
routes/index.js
const express = require('express');
const router = express.Router();
const db = require('../models/db'); // 假设你有一个数据库模块
// 渲染主页
router.get('/', async (req, res) => {
try {
const results = await db.query('SELECT * FROM some_table WHERE condition');
const results2 = await db.query('SELECT * FROM another_table WHERE condition');
res.render('index', {
header: results,
nav: results2,
user: req.user // 假设用户信息已经通过中间件设置
});
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
});
module.exports = router;
解释
-
局部模板:
header.ejs
和footer.ejs
被放在views/partials
文件夹中。这些文件包含重复的 HTML 代码片段。 -
主视图文件:
index.ejs
中使用<%- include('partials/header'); %>
来引入局部模板。这样,每次渲染index.ejs
时,都会自动包含header.ejs
的内容。 -
数据传递:在路由处理函数中,我们查询数据库并将结果传递给视图。这些数据可以在局部模板中使用,而不需要在每个页面中重复调用数据库。
通过这种方式,你可以有效地管理和重用代码,同时保持代码的整洁和高效。
只用浏览器端模板knockout.js的路过
在使用 Express 和 EJS 模板引擎时,为了提高性能和代码复用性,可以将 header
和 footer
等局部视图单独渲染,并通过局部变量的方式传递数据。这样可以避免在每次渲染页面时重复读取相同的数据。
解决方案
-
创建局部视图:
- 将
header.ejs
视为一个局部视图。
- 将
-
使用局部变量:
- 在渲染主视图(如
index.ejs
)时,只传递一次数据库查询结果。
- 在渲染主视图(如
-
优化路由处理函数:
- 使用中间件来提前获取数据,然后将这些数据传递给所有后续的渲染操作。
示例代码
假设我们有一个数据库查询函数 getHeaderData
,用于获取 header
的数据。
// 获取 header 数据的函数
const getHeaderData = async (req, res, next) => {
try {
const headerData = await fetchHeaderDataFromDatabase();
req.headerData = headerData;
next();
} catch (error) {
console.error('Error fetching header data:', error);
next(error);
}
};
// 路由处理函数
app.get('/', getHeaderData, (req, res) => {
res.render('index', { nav: req.navData });
});
// 在 index.ejs 中引用 header.ejs
<%- include('header.ejs', { headerData: headerData }) %>
具体步骤
-
定义中间件:
- 创建一个中间件
getHeaderData
,用于获取header
数据并将其附加到请求对象上。
- 创建一个中间件
-
路由处理:
- 在路由处理函数中使用这个中间件,确保在渲染
index
页面之前已经获取了header
数据。
- 在路由处理函数中使用这个中间件,确保在渲染
-
EJS 渲染:
- 在
index.ejs
中使用<%- include('header.ejs', { headerData: headerData }) %>
包含局部视图,并传递局部变量。
- 在
这样,header
数据只需查询一次,而不是在每次渲染页面时都重新查询。这不仅提高了性能,还使代码更加清晰和易于维护。