NodeJS
Web框架
Express
代码示例:
// index.js
const express = require('express')
const app = express()
app.get('/', (req, res) => {
// res.send('Hello World!')
// res.send(`
// <html lang="zh-CN">
// <h1>h1</h1>
// </html>
// `)
res.send({
name: 'HQSY',
age: 24
})
})
app.get('/login', (req, res) => {
res.write('login')
res.end()
})
app.listen(3000, () => {
console.log('server start')
})
路由
代码示例:
// index.js
const express = require('express')
const app = express()
app.get('/ab?cd', (req, res) => {
res.send('ok') // ?:可选的
})
app.get('/abc/:foo/:bar', (req, res) => {
res.send('ok') // 占位符
})
app.get('/ab+cd', (req, res) => {
res.send('ok') // +:一个或以上
})
app.get('/ab*cd', (req, res) => {
res.send('ok') // *:任意多个字符
})
app.get('/ab(cd)?e', (req, res) => {
res.send('ok') // ()?:存在或不存在
})
// 正则表达式写法
app.get(/.*foo$/,(req, res) => {
res.send('ok')
})
app.listen(3000, () => {
console.log('server start')
})
基本中间件
代码示例:
// index.js
const express = require('express')
const app = express()
// 第一种写法
app.get('/home', (req, res, next) => {
const isValid = true // 模拟验证
isValid ? next() : res.send('error') // next():是否继续执行下一个中间件(回调函数)
}, (req, res) => {
res.send({list: [1, 2, 3]})
})
app.listen(3000, () => {
console.log('server start')
})
// index.js
const express = require('express')
const app = express()
const func01 = (req, res, next) => {
const isValid = true
isValid ? next() : res.send('error') // 把next()写在send()后面时next()并不会被执行
// 要想把第一个中间件的执行结构传递给第二个中间件,可以在next()之前配置
}
const func02 = (req, res) => {
res.send({list: [1, 2, 3]})
}
// 第二种写法
app.get('/home', [func01, func02])
app.get('/list', [func01], (req, res) => {
res.send({list: [1, 2, 3]})
})
app.listen(3000, () => {
console.log('server start')
})
应用级中间件
代码示例:
// index.js
// 凡是挂在app下的方法都是应用级别的中间件
const express = require('express')
const app = express()
const func01 = (req, res, next) => {
const isValid = true
isValid ? next() : res.send('error')
}
const func02 = (req, res) => {
res.send({list: [1, 2, 3]})
}
// app.use(func01) // 以下的路由都会触发func01
app.use('/list', func01)
app.get('/home', [func02])
app.get('/list', (req, res) => {
res.send({list: [1, 2, 3]})
})
app.listen(3000, () => {
console.log('server start')
})
路由级中间件
代码示例:
// index.js
const express = require('express')
const app = express()
const {router} = require('./router/IndexRouter')
app.use('/', router)
app.listen(3000, () => {
console.log('server start')
})
// router/IndexRouter.js
// 凡是挂在router下的方法都是应用级别的中间件
const express = require('express')
const router = express.Router()
router.get('/home', (req, res) => {
res.send('ok')
})
router.get('/login', (req, res) => {
res.send('ok')
})
module.exports = {
router
}
// index.js
// 第二种写法
const express = require('express')
const app = express()
const HomeRouter = require('./router/HomeRouter')
const LoginRouter = require('./router/LoginRouter')
app.use('/home', HomeRouter)
app.use('/login', LoginRouter)
app.listen(3000, () => {
console.log('server start')
})
// router/HomeRouter.js
const express = require('express')
const router = express.Router()
router.get('/', (req, res) => {
res.send('ok')
})
module.exports = router
// router/LoginRouter.js
const express = require('express')
const router = express.Router()
router.get('/', (req, res) => {
res.send('ok')
})
module.exports = router
错误处理中间件
代码示例:
// index.js
const express = require('express')
const app = express()
const HomeRouter = require('./router/HomeRouter')
const LoginRouter = require('./router/LoginRouter')
app.use('/home', HomeRouter)
app.use('/login', LoginRouter)
app.use((err, req, res, next) => {
res.status(404).send('找不到页面') // 必须放到最后面
})
app.listen(3000, () => {
console.log('server start')
})
内置中间件
代码示例:
// index.js
const express = require('express')
const app = express()
const HomeRouter = require('./router/HomeRouter')
const LoginRouter = require('./router/LoginRouter')
// 解析post参数
app.use(express.urlencoded({extended: false})) // form
app.use(express.json()) // json
app.use('/home', HomeRouter)
app.use('/login', LoginRouter)
app.listen(3000, () => {
console.log('server start')
})
// router/LoginRouter.js
const express = require('express')
const router = express.Router()
router.get('/', (req, res) => {
// console.log(req.query)
res.send('ok')
})
router.post('/', (req, res) => {
console.log(req.body) // 必须配置中间件
res.send({ok: 1})
})
module.exports = router
静态资源
代码示例:
// index.js
const express = require('express')
const app = express()
const HomeRouter = require('./router/HomeRouter')
const LoginRouter = require('./router/LoginRouter')
// 配置静态资源
app.use(express.static('public'))
// app.use('/public',express.static('public'))
app.use(express.urlencoded({extended: false}))
app.use(express.json())
app.use('/home', HomeRouter)
app.use('/login', LoginRouter)
app.listen(3000, () => {
console.log('server start')
})
// router/LoginRouter.js
const express = require('express')
const router = express.Router()
router.get('/', (req, res) => {
console.log(req.query)
res.send('ok')
})
router.post('/', (req, res) => {
console.log(req.body)
const {username, pwd} = req.body
if (username === 'username' && pwd === 'password') {
res.send({ok: 1})
} else {
res.send({ok: 0})
}
})
module.exports = router
/* public/css/home.css */
div {
background-color: #30363d;
}
<!-- public/login.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
用户名:<input type="text" id="useName"/>
</div>
<div>
密码:<input type="password" id="pwd"/>
</div>
<div>
<button id="loginGet">登录-GET</button>
<button id="loginPost">登录-POST</button>
</div>
<script>
const useName = document.querySelector('#useName')
const pwd = document.querySelector('#pwd')
const loginGet = document.querySelector('#loginGet')
const loginPost = document.querySelector('#loginPost')
loginGet.onclick = () => {
fetch(`/login?username=${useName.value}&pwd=${pwd.value}`)
.then(res => res.text())
.then(res => console.log(res))
.catch(err => console.log(err))
}
loginPost.onclick = () => {
fetch(`/login`, {
method: 'POST',
body: JSON.stringify({
username: useName.value,
pwd: pwd.value
}),
headers: {
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(res => {
console.log(res)
if (res.ok === 1) {
location.href = '/home.html'
} else {
window.alert('用户名或密码错误错误')
}
})
.catch(err => console.log(err))
}
</script>
</body>
</html>
<!-- public/home.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/css/home.css">
</head>
<body>
<div>
欢迎回来
</div>
</body>
</html>
服务端与客户端渲染
代码示例:
// index.js
const express = require('express')
const app = express()
const HomeRouter = require('./router/HomeRouter')
const LoginRouter = require('./router/LoginRouter')
// 配置模板引擎
app.set('views', './views')
app.set('view engine', 'ejs')
// app.set('view engine', 'html')
// app.engine('html', require('ejs').renderFile) // 指定HTML模板是用EJS语法解析
app.use(express.static('public'))
app.use(express.urlencoded({extended: false}))
app.use(express.json())
app.use('/home', HomeRouter)
app.use('/login', LoginRouter)
app.listen(3000, () => {
console.log('server start')
})
// router/LoginRouter.js
const express = require('express')
const router = express.Router()
router.get('/', (req, res) => {
// send方法可以是HTML片段或JSON
// json方法只能是JSON
res.render('login', {error: '', isShow: false}) // 渲染模板后返出给前端(会根据配置寻找views文件夹下的login.ejs)
})
router.post('/', (req, res) => {
if (req.body.username === 'username' && req.body.pwd === 'password') {
res.redirect('/home')
} else {
res.render('login', {error: '用户名或密码错误!', isShow: true})
}
})
module.exports = router
// router/HomeRouter.js
const express = require('express')
const router = express.Router()
router.get('/', (req, res) => {
res.render('home', {list: ['aaa', 'bbb', 'ccc'], html: '<h1>h1</h1>'})
})
module.exports = router
<!-- views/login.ejs -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="POST">
<div>
用户名:<input type="text" name="username">
</div>
<div>
密码:<input type="password" name="pwd">
</div>
<div>
<input type="submit" value="登录">
</div>
</form>
<p><%=error%></p>
<p><%=isShow?'用户名或密码错误': ''%></p>
</body>
</html>
<!-- views/home.ejs -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<%- include('./header.ejs', {isShowTitle: false})%>
<ul>
<%for (let i = 0; i < list.length; i++) {%>
<li><%= list[i]%></li>
<%}%>
</ul>
<div><%- html%></div>
<%# 注释(并不会显示在前端的页面源码中)%>
</body>
</html>
<!-- views/header.ejs -->
<header>
<% if (isShowTitle) {%>
<h1>h1</h1>
<%}%>
<h2>h2</h2>
</header>