13 KiB
Executable File
13 KiB
Executable File
Node开发框架——Express
注意项:
- 引入自定义模块要用相对路径, 如
./
简介
官网: https://www.expressjs.com.cn/
Express是一个Node.js Web 应用程序开发框架 最肤浅理解: 路由框架
核心特性:
- 路由: 定义了路由表用于执行不同的 HTTP 请求动作。
- 中间件: 本质是一个函数, 在收到请求和返回响应的过程中进行处理
- 模版引擎: ......
类似的框架
fastify koa koa2
使用
//初始化, 创建package.json文件
npm init -y
//安装express到项目
npm i express -S
//引入Express框架
const express = require('express')
//创建一个web服务器
const app = express()
//给app对象注册一个中间器,use是一个内置中间件,可以用来监听get和post请求
app.use((req, res) => res.send('Hello World!'))
//开启服务器并监听端口
app.listen(3000, ()=>{
console.log('http://127.0.0.1:300')
})
使用express-generator生成项目骨架
......
中间件
中间件功能可以执行以下任务:
- 执行任何代码。
- 更改请求和响应对象。
- 结束请求-响应周期。
- 调用堆栈中的下一个中间件函数。
中间件的分类:
- 应用层中间件
- 路由器级中间件
- 错误处理中间件
- 内置中间件
- 第三方中间件
应用层中间件
使用use()
或者METHOD()
绑定函数到应用程序实例app上, METHOD 包括get和post
- ==中间件是有顺序的==
- next() 放行, 触发后续的中间件. 不放行, 后面的中间件都不执行.
- next() 不能在响应处理完毕后调用. 举例: res.send() 后不能再接 next()
const app = express()
//每个请求都会执行
app.use(function (req, res, next) {
console.log('Time:', Date.now())
next()
})
//访问根目录时会执行
app.use('/', (req, res, next) {
console.log('Time:', Date.now())
next()
})
路由器中间件
使用router.use()
和router.METHOD()
函数加载路由器级中间件。
// 创建路由对象
const router = express.Router()
router.get('/', function (req, res) {
res.send('hello, user!')
})
//安装路由
app.use(router)
错误处理中间件
//错误处理中间件始终带有四个参数, 不能省略
app.use(function (err, req, res, next) {
console.error(err.stack)
res.status(500).send('Something broke!')
})
//要写在路由安装之后
内置中间件
Express具有以下内置的中间件功能:
- express.static : 提供静态资产,例如HTML文件,图像等。
// 中间件有顺序, 哪个在前, 哪个先生效
//实现静态页面的自动访问,它会默认打开views下面的index.html
app.use('/', express.static(path.join(__dirname, 'views')))
// 响应静态资源
app.use(express.static('public'))
-
express.json: 。它使用JSON有效负载分析传入请求,并基于body-parser
app.use(bodyParser.json()) //接受一个对象或数组,并在发送之前将其转换为JSON res.json({ code: 204, msg: '注册失败' })
第三方中间件
通过使用第三方中间件从而为Express应用增加更加功能
安装所需要功能的node模块,并在应用中加载,可以在应用级加载,也可以在路由级加载。
- bodyParse: 处理程序之前,在中间件中对传入的请求体进行解析
//先安装再使用
npm i body-parser -S
const bodyPsrse = require('body-parser')
...
//bodyParser.json是用来解析json数据格式的
app.use(bodyParser.json())
//bodyParser.urlencoded则用来解析我们通常的form表单提交的数据
app.use(bodyParser.urlencoded({
extended: false
//设置为false采用querystring库,如果设置为true那么采用qs库, 官方建议false
}))
//body-parse不支持FormData, 但post的其他数据都可以用它来接收
//get参数用express自带的req.query接收
路由
参数:
-
请求方式:
app.get() app.post() app.put() app.delete() app.all()
-
请求路径: 只匹配对应路径的请求进行处理
app.get('/', function (req, res) { res.send('只响应根路由/') }) app.get('/random.text', function (req, res) { res.send('只响应/random.text') })
-
处理方法:
//单个回调函数
app.get('/example/a', function (req, res) {
res.send('Hello from A!')
})
//多个回调函数可以处理一条路由, 使用next()
app.get('/example/b', function (req, res, next) {
console.log('the response will be sent by the next function ...')
next()
}, function (req, res) {
res.send('Hello from B!')
})
项目
//1.规划项目文件夹
Demo
-data 数据
-node_modules 第三方模块
-public 公共资源
-css
-images
-js
-views 静态页面资源
-index.html 首页
-register
-app.js 程序入口
-handler.js 业务处理模块
-router.js 路由表
-package.json
-package-lock.json
//2. 引入内置模块
//3. 创建服务器, 监听端口
//4. 响应页面资源
//5. 静态资源托管
//6. 添加路由表 router.js
//7. 业务功能处理 handle.js
//8. 安装路由
程序入口 app.js
const express = require('express')
const path = require('node:path')
const router = require('./router')
const bodyParser = require('body-parser')
let app = express()
app.listen(3002, () => {
console.log('127.0.0.1:3002')
})
// 添加body-parse解析器,使用它进行处理post方式所传递的参数
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: false
}))
//static中间函数实现静态页面的自动访问
app.use('/', express.static(path.join(__dirname, 'views')))
//响应静态资源
app.use(express.static('public'))
//安装路由功能
app.use(router)
// 路由可以安装多个, 中间件都是有顺序的
// app.use('url1', router1) // 都在url1下, 路径为url1/xxx
// app.use('url2', router1)
路由表router.js
// 引入express
const express = require('express')
const handler = require('./handler')
// 创建路由对象
const router = express.Router()
// 添加(挂载)路由配置
router.post('/register', (req, res) => {
handler.userRegister(req, res)
})
// 暴露
module.exports = router
业务处理 handler.js
const fs = require('node:fs/promises')
const path = require('node:path')
// 专门进行业务处理
module.exports = {
userRegister: function (req, res) {
// express封装了get请求参数的接收
// req.query 是express自带的
// 接收用户参数 以前req.on('data') req.on('end') > 参数的类型转换
// body:就是post方式所传递的参数,它是一个对象(参数的接收和参数的转换)
// console.log(req.body)
// 存储到指定的数据文件中,并响应结果
getRegister: (req,res) => {
console.log('req.body', req.body)
fs.readFile(path.resolve(__dirname, './data/users.json'),'utf-8')
.then(data=>{
let arr = JSON.parse(data)
arr.push(req.body)
return fs.writeFile(path.resolve(__dirname,'./data/users.json'),JSON.stringify(arr, null, ' '))
})
.then(result => {
res.json({code:200,msg:'注册成功'})
})
.catch(err=>{
console.log('err', err)
res.json({code:204,msg:'注册失败'})
})
}
}
- 重定向: res.redirect(path)
- 设置响应状态码:
res.status(404).send('404 not found')
用户认证
另建笔记
模板引擎(了解)
服务端渲染:
优势 | 劣势 | |
---|---|---|
服务端 | 1. 前端耗时少 2. 有利SEO 3. 客户端速度更快, 耗电更少 |
1. 不利于前后端分离, 开发效率低 2. 请求多时, 对服务器造成访问压力 |
折中方案: "首屏渲染", 首屏加载用服务器渲染,其他的用客户端渲染
模板引擎有很多: Template Engines
其中: 前台模板引擎 express-art-template 介绍 - art-template
使用步骤:
- 下载安装
- 先下载art-template:
npm i art-template -S
- 再下载express-art-template:
npm i express-art-template -S
- 先下载art-template:
- 给express框架设置默认的模板引擎
// 注册模板引擎
app.engine('html', require('express-art-template')); //第一个参数是渲染文件的格式
app.set('view options', {
debug: process.env.NODE_ENV !== 'production' //设置模板引擎的使用环境, 开发和上线都要使用
});
- 设置模板引擎文件的默认路径
// 如果不设置,默认也是views
app.set('views',path.join(__dirname, './views')
app.set('view engine', 'html') //设置模板文件的类型
示例如下:
// 1. 引入框架模块
var express = require('express')
// 2. 创建服务器
var app = express();
// 注册模板引擎
//engine就是个中间件
app.engine('html', require('express-art-template'));
app.set('view options', {
debug: process.env.NODE_ENV !== 'production'
});
// 如果不设置,默认也是views
//app.set('views','./views')
// 3. 开启服务器并监听端口
app.listen(3000,()=>{
console.log('http://127.0.0.1:3000')
})
app.get('/login',function(req,res){
// 引入express-art-template之前,会在Res上挂载一个render方法,可以实现页面的渲染
// render实现的功能有: 读取文件,动态渲染,响应, 所以不用fs去读文件
// res.render(要渲染的文件路径,[数据])
res.render('login.html', { list: [{ name: 'jack', age: 20 }, { name: 'rose', age: 18 }] })
})
/views/login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
{{each list}}
<li>{{$value.name}} -- {{$value.age}}</li>
{{/each}}
</ul>
<!--
//后台的模板不是使用script标签来创建模板
整个页面就是模板
-->
<form action="">
用户名: <input type="text"> <br>
密码 <input type="text"> <br>
<button>登陆</button>
</form>
</body>
</html>
node操作mysql
const express = require('express')
// 导入MySQL模块
const mysql = require('mysql');
const app = express()
app.listen('3008', () => {
console.log('http://127.0.0.1:3008')
})
// 创建一个数据库连接, 用createPool不用createConnection
var connection = mysql.createPool({
host: '127.0.0.1', // 数据库服务器的地址
user: 'root', // 数据库的账号
password: 'root', // 数据库的密码
database: 'mybase58' // 数据库名称, 不是表的名称
});
// 连接数据库或打开数据库
//connection.connect();
//不用手动打开链接
app.get('/', (req, res) => {
//查
// let sql = `select * from users`
//增
// let obj = {
// name: '赵六',
// age: '26',
// address: '赵家村'
// }
// let sql = `insert into users (name, age, address) value ('${obj.name}', '${obj.age}', '${obj.address}')`
//注意: value里面的字符串要主动加引号
//除了查询, 增删改的fields没有定义
//查询返回的是所有的数据, 增删改返回的是okPacket
//改
// let obj = {
// id: 8,
// age: 25
// }
// let sql = `update users set age = '${obj.age}' where id = '${obj.id}'`
//删
let obj = {
name: '赵六',
}
let sql = `delete from users where name = '${obj.name}'`
connection.query(sql, (err, results, fields) => {
if (err) {
console.log(err)
throw err
} else {
console.log(results)
console.log(typeof results)
console.log('-----------------')
console.log(fields)
}
})
})
简洁写法
//参数查询
let sql = 'select * from users where name = ?'
connection.query(sql, ['张三'], (err, results, fields) => {
if (err) {
console.log(err)
throw err
} else {
console.log(results)
}
})
//增
let obj = {
name: '赵六1212',
age: '26',
address: '赵家村'
}
let sql = `insert into users set ?`
connection.query(sql, obj, (err, results, fields) => {
if (err) {
console.log(err)
throw err
} else {
console.log(results)
}
})
//改
let obj = {
id: 5,
name: '赵六1212',
age: '27',
address: '赵家村'
}
let sql = `update users set ? where id = ?`
connection.query(sql, [obj, obj.id], (err, results, fields) => {
//第二个参数, 如果只有一个是对象, 直接写, 如果是多个参数, 加上方括号成数组
if (err) {
console.log(err)
throw err
} else {
console.log(results)
}
})
//删除
let sql = 'delete from users where id = ?'
connection.query(sql, [2], (err, results, fields) => {
if (err) {
console.log(err)
throw err
} else {
console.log(results)
}
})
let sql = 'delete from users where name = ?'
connection.query(sql, ['李八'], (err, results, fields) => {
if (err) {
console.log(err)
throw err
} else {
console.log(results)
}
})