HTML 页面
本课属于 Coddy Node.js 学习旅程的“Express 基础”单元。第 10 课,共 23 课。
Recipe Box 现在会把 HTML 字符串和转义练习变成一个页面。为每个食谱创建一个链接。链接的 href 用来选择目标位置,标签之间的文本就是读者看到的标签。
const link = `<a href="/books/${book.id}">${escapeHtml(book.title)}</a>`;html.js 中提供了这个辅助函数。对每个标题应用它,同时将你自己的链接标签保留为标记。使用 map 创建链接,再用 join 将它们合并为一个字符串。直接在模板字符串中放入数组会在链接之间插入逗号。res.send 会将完整页面发送给浏览器。
<ul> 用来存放列表,<li> 用来包裹每个列表项。未转义的标记可能会更改页面,或在访客的浏览器中运行脚本;即使标题来自你自己的数据文件,也要逐个转义。
挑战
简单这一步会打开课程中准备好的 Recipe Box 项目,而不是你在 Status Codes 中的项目文件(包括 server.js)。你之前的工作仍保留在原来的课中。编辑 server.js 前,先阅读提供的文件。这份项目副本包含 Recipe Box 路由、状态码和共享的 html.js 辅助工具。
现在,主页会成为一个真正的页面:列出所有菜谱,每个菜谱都链接到自己的页面。
- 在
server.js中,从./html.js导入提供的escapeHtml辅助函数。 - 修改
/路由,让它发送 HTML 页面,而不是欢迎文本。页面中每个菜谱都有一个链接,指向该菜谱的页面,并显示菜谱标题。菜谱 2 的链接如下:<a href="/recipes/2">Pancakes</a>。使用列表很合适:每个链接放在一个<li>项中,所有项目都放在一个<ul>中。你可以从一个标题开始:<h1>Recipe Box</h1>。 - 将每个标题传入
escapeHtml,再放入页面。这样,Fish & Chips 会以Fish & Chips的形式进入页面,浏览器会将其显示为 Fish & Chips。 - 使用
map构建这些项目,并用空字符串将它们连接起来。如果直接把数组放进模板字符串中,项目之间会出现逗号。
试试看:点击“运行”,然后访问 /。响应会以包含 4 个链接的页面形式呈现。点击 Fish & Chips:/recipes/4 页面会打开,并显示 Fish & Chips。
亲手试试
import express from 'express';
import { recipes } from './data.js';
const app = express();
app.get('/', (req, res) => {
res.send('Welcome to Recipe Box');
});
// type('text') 会发送纯文本,所以每个标题都会单独显示在一行。
app.get('/recipes', (req, res) => {
const { tag } = req.query;
const list = tag ? recipes.filter((recipe) => recipe.tags.includes(tag)) : recipes;
res.type('text').send(list.map((recipe) => recipe.title).join('\n'));
});
app.get('/recipes/:id', (req, res) => {
const recipe = recipes.find((r) => r.id === Number(req.params.id));
if (!recipe) {
res.status(404).send('No such recipe');
return;
}
res.send(recipe.title);
});
app.get('/api/recipes', (req, res) => {
res.json(recipes);
});
app.get('/api/recipes/:id', (req, res) => {
const recipe = recipes.find((r) => r.id === Number(req.params.id));
if (!recipe) {
res.status(404).json({ error: 'No such recipe' });
return;
}
res.json(recipe);
});
app.get('/about', (req, res) => {
res.send('Recipe Box collects family recipes.');
});
app.listen(3000, () => {
console.log('Recipe Box is running on port 3000');
});
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
Express 基础中的所有课
自己练习: Express 在线编辑器