Node.js + Express + Pug
html vs. pug
导航栏:
- overview.html版本
<header class="header">
<nav class="nav nav--shows">
<a href="#" class="nav__el">所有演出</a>
<form class="nav__search">
<button class="nav__search-btn">
<svg>
<use xlink:href="img/icons.svg#icon-search"></use>
</svg>
</button>
<input
type="text"
placeholder="搜索演出"
class="nav__search-input"
/>
</form>
</nav>
<div class="header__logo">
<img src="img/logo-white.png" alt="Nashows logo" />
</div>
<nav class="nav nav--user">
<a href="#" class="nav__el">退出登录</a>
<a href="#" class="nav__el">
<img src="img/user.jpg" alt="User photo" class="nav__user-img" />
<span>USERNAME</span>
</a>
</nav>
</header>
- overview.pug版本
header.header
nav.nav.nav--shows
a.nav__el(href='/') 所有演出
form.nav__search
button.nav__search-btn
svg
use(xlink:href="/img/icons.svg#icon-search")
input.nav__search-input(type="text",placeholder="搜索演出")
.header__logo
img(src='/img/logo-white.png' alt='Saturn logo')
nav.nav.nav--user
a#logoutBtn.nav__el.nav__el--logout(href='/') 退出登录
a.nav__el(href='/me')
span= user.name
快速使用
安装pug
npm i pug
app.set
根目录中创建views文件夹储存模板文件。Express App 中设置:
//创建express应用
const app = express();
const path = require('path');
// 设置模板类型
app.set('view engine', 'pug');
// 设置模板文件路径
app.set('views', path.join(__dirname, 'views'));
服务端渲染页面
get请求
实现:在浏览器地址栏输入http://localhost:3000 ,得到所有演出信息
创建路由
const viewRouter = express.Router();
const getOverview = ...设置处理器
viewRouter.get('/',getOverview);
app.use('/',viewRouter);
render('模板名称', 参数列表)
getOverview = catchAsync(async (req, res, next) => {
const shows = await Show.find();
res.status(200).render('overview', {
title: '所有演出',
shows
});
});
前端请求
get -query
实现:在前端页面头部导航栏搜索框中输入查询,后端返回所有名称中含有查询字符串的演出信息。
思路:请求需要传递参数,利用查询url,即实现前端点击搜索按钮(提交表单),读取input框信息请求后端页面,后端根据查询字符串从数据库中选择相应信息。
前端请求
提交表单:
const navSearchForm = document.querySelector('.nav__search');
读取信息:
if (navSearchForm) {
navSearchForm.addEventListener('submit', event => {
event.preventDefault()
const filter = document.querySelector('.nav__search-input').value;
search(filter);
});
}
向后端发送带参数的get请求,请求成功返回网址由location指定:
const search = async filter => {
try {
const res = await axios({
method: 'GET',
url: `http://localhost:3000/?filter=${filter}`
});
if (res.status === 200) {
location.assign(`/?filter=${filter}`)
}
} catch (err) {
console.log(err);
}
};
后端模板路由
mongoose提供的find方法,正则匹配:
Show.find({ name: {$regex: /regexp/ig }})
const getOverview = catchAsync(async (req, res, next) => {
if (req.query.filter === '' || req.query.filter === undefined) {
const shows = await Show.find();
return res.status(200).render('overview', {
title: '所有演出',
shows
});
} else {
const filter = new RegExp(`${req.query.filter}`, 'i');
const shows = await Show.find({ name: { $regex: filter } });
if (shows.length === 0) {
res.status(200).render('error', {
title: '出错了!',
msg: '没有找到对应的演出,请重新输入关键词查询!'
});
}
res.status(200).render('overview', {
title: '所有演出',
shows
});
}
});