2025/12/14

一、node.js介绍

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,让 JavaScript 脱离浏览器运行在服务器端 / 本地环境,彻底改变了 JavaScript 仅作为 “前端脚本语言” 的定位,成为全栈开发、高性能服务端开发的核心技术之一。

二、安装node.js

https://nodejs.cn/download/#google_vignette 官网下载

node -v 查看安装是否成功

三、fs模块

引入模块:const fs = require(‘fs’)

1
2
3
4
写入数据:fs.writeFile(file, data[, options], callback)	文件名,写入的数据,模式,回调函数

如: fs.writeFile('test.txt',"你好",{flag:a},err => {错误}) flag: w 默认,写入 a为追加
注:异步方法
1
2
3
4
写入数据:fs.writeFileSync(file, data[, options])		文件名,数据,模式

如:fs.writeFileSync('test.txt',"你好",{flag:a})
注:同步方法
1
追加数据:fs.appendFile(file, data[, options], callback)		和写入数据一样
1
2
3
4
5
6
流式调用:const ws = fs.createWriteStream()
ws.write('1') //写入数据
ws.write('2')
ws.write('3')
//关闭通道
ws.close()
1
2
3
4
读取数据:fs.readFile(file[, options], callback)			文件名,模式,回调函数

如:fs.readFile('test.txt',err => {错误})
注:异步方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
流式读取:const readStream = fs.createReadStream(file,{highWaterMark: 字节});  文件名,读取字节,默认64k

// 2. 监听流事件(核心)
readStream.on('data', (chunk) => {
console.log(`读取到 ${chunk.length} 字节数据`);
});

// 3.读取完成触发
readStream.on('end', () => {
console.log('文件读取完成');
});

// 4.读取错误触发
readStream.on('error', (err) => {
console.error('读取失败:', err);
});

1
2
3
4
5
6
管道复制文件:
const readStream = fs.createReadStream(file,{highWaterMark: 字节}); 读取
const ws = fs.createWriteStream(file) 写入

readStream.pipe(ws) //管道读取

1
文件重命名和移动:fs.rename(oldPath, newPath, callback)		旧文件,新文件,回调函数
1
2
文件删除: fs.unlink(file,callback)	文件名,回调函数					方式2: fs.rm(file,callback)
查看文件属性: fs.stat(file,(err,data) => 数据)

文件夹操作

1
2
3
创建目录:fs.mkdir(dirPath, { recursive: true },callback)	目录名,是否开启多目录创建,回调函数
读取文件夹内容,以数组形式存储:fs.readdir(dirPath,(err,data) => {数据})
删除文件夹: fs.rm(dirPath,{ recursive: true },callback)

文件路径全局变量

1
_dirname	当前文件夹绝对路径			_filename	当前文件绝对路径

四、path模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const path = require('path')	引入
一、路径分隔符 / 环境变量分隔符(常量)

path.sep:表示当前系统的路径分隔符(Windows 为反斜杠 \,POSIX 系统如 Linux/Mac 为正斜杠 /),用于拆分 / 拼接路径片段时适配系统。
path.delimiter:表示当前系统的环境变量分隔符(Windows 为分号 ;,POSIX 系统为冒号 :),用于处理 PATH 等环境变量字符串。

二、路径拼接与解析(核心)

path.join([...paths]):将多个路径片段拼接为规范化的路径字符串,自动处理多余的分隔符、.(当前目录)和 ..(上级目录),跨平台兼容。
path.resolve([...paths]):将多个路径片段解析为绝对路径,规则为:从右到左拼接片段,若某片段为绝对路径则停止拼接并基于该路径生成绝对路径;若所有片段均为相对路径,则基于当前进程工作目录生成绝对路径,同时自动处理 ./..。
path.normalize(path):规范化路径字符串,清理多余的分隔符、修复 ./.. 带来的路径混乱,统一路径格式(如将 /usr//local/../bin 转为 /usr/bin)。

三、路径信息提取与构造
path.parse(path):将路径字符串解析为包含路径各组成部分的对象,对象属性包括:
root:路径的根目录(如 POSIX 的 /、WindowsC:\);
dir:文件 / 目录所在的完整目录路径;
base:文件名(包含扩展名);
name:纯文件名(不含扩展名);
ext:文件扩展名(从最后一个 . 到路径末尾,无 . 则为空)。
path.format(pathObj):path.parse() 的反向操作,将包含路径各组成部分的对象还原为规范化的路径字符串。
path.extname(path):提取路径中文件的扩展名,规则为取最后一个 . 之后的字符(无 . 则返回空,多后缀文件如 file.tar.gz 仅返回最后一个后缀 .gz)。
path.basename(path[, ext]):提取路径中的文件名(base 部分),可选参数 ext 用于剔除扩展名(如传入 .txt 则返回不含 .txt 的纯文件名)。
path.dirname(path):提取路径中的目录部分(即 parse 结果中的 dir 属性),返回文件 / 目录所在的上级目录路径。

四、路径关系判断与计算
path.isAbsolute(path):判断传入的路径是否为绝对路径(绝对路径以根目录开头,如 POSIX 的 /usr、WindowsC:\docs)。
path.relative(from, to):计算从 from 路径到 to 路径的相对路径,返回的字符串表示从 from 出发到达 to 所需的路径(如从 /a/b 到 /a/c/d 则返回 ../c/d)。

五、跨平台路径模式(子模块)
path.posix:强制使用 POSIX 系统的路径规则(无论当前系统类型),其下包含与 path 主模块完全相同的方法(如 path.posix.join、path.posix.sep),分隔符固定为 /,用于跨平台统一路径格式。
path.win32:强制使用 Windows 系统的路径规则(无论当前系统类型),其下方法分隔符固定为 \,仅用于非 Windows 系统模拟 Windows 路径场景。

五、http模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//快速入门
const http = require('http') //引入


//创建服务对象
const server = http.createServer((req,resp) => { //里面为回调函数
resp.setHeader("content-type","text/html;charset=utf-8") //设置编码字符
resp.end('你好,已做乱码设置') //设置响应体

})

//监听端口
server.listen(9000,() => {
console.log("服务已经启动");

})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//获取报文		使用req
const server = http.createServer((req,resp) => {
//获取请求方法
console.log(req.method); // GET
//获取请求 url
console.log(req.url); // /
//获取http协议版本号
console.log(req.httpVersion); // 1.1
//获取请求头
console.log(req.headers);
//获取请求头的主机名
console.log(req.headers.host);
//获取请求头状态码
console.log(req.statusCode);

resp.end("hello")
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//获取请求头数据		如: localhost:9090?name=ss&pass=2323		后面的name=ss&pass=2323	必须为post请求
const server = http.createServer((req,resp) => {
//1.声明变量
let body = ''
//2.绑定事件
req.on('data',chunk => { //on为事件
body += chunk //chunk为每次读取的数据,一点点的放入到body
})
req.on('end',() => {
console.log(body)
resp.end("tool")
})

})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//获取路径和参数		如: http://localhost:9000?word=h5
//创建服务对象
const server = http.createServer((req,resp) => {
const baseUrl = `http://${req.headers.host}`;
const url = new URL(req.url,baseUrl)
console.log(url);
//获取参数
console.log(url.searchParams.get('word')); //h5

resp.setHeader("content-type","text/html;charset=utf-8")
resp.end('你好,已做乱码设置') //设置响应体

})

//监听端口
server.listen(9000,() => {
console.log("服务已经启动");

})

六、MIME类型

媒体类型,是一种标准,用于表示文档、文字或字节流的性质和格式

mime格式: [type]/[subType]

以下是常见格式

1
2
3
4
5
6
7
8
html:  'text/html'
css: 'text/css'
js: 'text/javascript'
png: 'image/png'
jpg: 'image/jpg'
gif: 'image/gif'
mp4: 'video/mp4' mp3: 'video/mpeg'
json: 'application/json'

七、模块化

模块化是编程中将复杂程序拆分为独立、可复用的小模块的思想,核心目标是降低代码耦合、提升可维护性 / 复用性,JavaScript 作为弱类型脚本语言,模块化规范经历了从无到有、从社区方案到原生支持的过程。

CommonJS 规范(Node.js 核心)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 定义模块(module.js)
const foo = 'hello';
function bar() {
return foo;
}
// 方式1:exports.函数名/属性/对象 单个
exports.foo = foo; //暴露属性
exports.bar = bar;

// 方式2:module.exports = 函数名/属性/对象 多个
module.exports = { foo, bar };


// 引入模块(main.js)
const { bar } = require('./module.js'); // 相对路径,后缀可省略
console.log(bar());

//注:可以省略 .js和.json文件的后缀,如:const bar = require('./me') 优先引入js文件后json文件 如果导入文件夹可以省略./

ES6规范 (js原生)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//常规导出	文件名 comm.js
// 先声明成员
const name = 'ES6 模块';
const version = 'ES2015';
function sayHello() {
return `Hello ${name}`;
}
class ModuleDemo {}

// 批量导出(对象字面量形式)
export { name, version, sayHello, ModuleDemo };

//注:也可以声明时直接导入: export const name = "xiaochen";

//导入方式:
import * as m from './comm.js' //导入所有,需要有as
import {name} from './comm.js' //导入单个或多个
import {name as n} from './comm.js' //导入重命名


///默认导出 文件名 sun.js
function sum(a,b){
return a + b
}

export default sum

//导入
import sss from './sun.js' //此时这里的名称可以随便自定义,因为一定是sum函数 一般用于匿名函数等
console.log(sss(1,33)) //34

八、包管理工具

包管理工具是前端 / Node.js 开发的 “管家”—— 帮你安装、更新、卸载、管理第三方代码包(比如 axios、Vue、React),还能处理包之间的依赖关系,不用手动下载、解压、配置,核心解决 “找包难、管依赖乱” 的问题。

1.npm包管理工具

它是node.js自带的 测试: npm -v

初始化创建包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//创建一个文件夹
1.指令: npm init 此时弹出下面 输入 npm init -y 全部按照默认创建

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (npm) 输入包名(英文且不可以为大写)
version: (1.0.0) 版本
description: 目的,随便取名
entry point: (index.js)
test command: 测试指令,没有跳过
git repository: git仓库,没有跳过
keywords: 关键字,没有跳过
author: itchen 作者名
license: (ISC)
About to write to E:\frontend\node.js\代码\包管理\npm\package.json:

{
"name": "test",
"version": "1.0.0",
"description": "learnNpm",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "itchen",
"license": "ISC"
}


Is this OK? (yes) 回车即可


操作类别 核心命令 功能与参数说明
📦 项目初始化 npm init 初始化新项目,创建 package.json(交互式问答)
npm init -y 快速初始化,使用默认配置
📥 依赖安装 npm installnpm i 安装 package.json 中所有依赖
npm install 包名 安装包到 dependencies
npm install 包名 --save-dev 安装包到 devDependencies(开发依赖)
`npm install -g 包名 全局安装包(用于命令行工具)
npm ci 严格按 package-lock.json 安装(适用于CI/CD)
🔄 依赖管理 `npm update 包名 更新指定包(遵循语义化版本)
npm uninstall 包名 或 npm r 包名 卸载指定包
npm list 列出已安装包(-g 全局,--depth 0 仅顶层)
npm outdated 检查过时的包
npm audit 安全审计,npm audit fix 尝试修复漏洞
🚀 运行与脚本 npm run <script> 运行 package.json 中定义的脚本
npm start 运行 start 脚本(run 可省略)
npm test 运行 test 脚本(run 可省略)
🔍 信息查询 npm view <package_name> 查看包的详细信息
npm search <keyword> 搜索包(在线搜索)
npm explain <package_name> 解释包被安装的原因(类似 yarn why
📤 包发布 npm login 登录到 npm 注册表
npm publish 发布包到 npm 注册表,也是更新
npm unpublish 取消发布(有限制条件)

注: npm i 包名@版本号 指定版本号

开发依赖和生产依赖

生产依赖: npm i -S uniq -S是默认 开发依赖: npm i -D uniq

npm配置别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//1.需要创建初始化包	npm init
//2.在包 "script" 下面配置别名
{
"name": "test",
"version": "1.0.0",
"description": "learnNpm",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"server": "node ./http.js" //配置启动类
"start": "node ./http.js" //这是第二种写法
},
"author": "itchen",
"license": "ISC",
"dependencies": {
"uniq": "^1.0.1"
}
}

//此时启动不是: node ./http.js 而是: npm run server 使用start: npm start

2.yarn包管理工具

Yarn 是一款JavaScript 包管理工具,最初由 Facebook 主导开发,核心解决 npm 早期版本的性能、可靠性、安全性问题,目前已成为与 npm 并列的主流包管理工具,兼容 npm 生态(可直接使用 npm 仓库的包)。速度比npm要快!!!!

1
npm i -g yarn		//全局安装
操作类别 核心命令 功能与参数说明
📦 项目初始化 yarn init 初始化新项目,创建 package.json 文件(交互式问答)
yarn init -y 快速初始化,使用默认配置创建 package.json
📥 依赖安装 yarnyarn install 安装 package.json 中所有依赖
yarn add <package_name> 安装包到 dependencies
yarn add <package_name> -D 安装包到 devDependencies(开发依赖)
yarn global add <package_name> 全局安装包(用于命令行工具)
🔄 依赖管理 yarn upgrade <package_name> 升级指定包到最新版本
yarn remove <package_name> 移除指定包
yarn list 列出已安装的包(--depth 0 仅显示顶层)
yarn outdated 检查过时的包
yarn audit 检查安全漏洞,yarn audit --fix 尝试修复
🚀 运行与脚本 yarn run <script> 运行 package.json 中定义的脚本
yarn start 运行 start 脚本(可省略 run
yarn test 运行 test 脚本(可省略 run
🔍 信息查询 yarn info <package_name> 查看包的详细信息(版本、依赖等)
yarn search <keyword> 搜索包(在线搜索)
yarn why <package_name> 解释为什么安装了某个包(依赖关系)
📤 包发布 yarn login 登录到 npm 注册表
yarn publish 发布包到 npm 注册表
yarn unpublish <package>@<version> 取消发布指定版本(有限制)
🛠️ 实用工具 yarn cache list 列出缓存包
yarn cache clean 清理缓存
yarn config set <key> <value> 设置配置(如镜像源)
yarn workspace <workspace> <command> 在指定工作区运行命令(Monorepo)

3.nvm

用于切换node版本,如果你当前的node版本是18,而需要16,可以直接切换,这里不演示了

九、Express框架

Express 是基于 Node.js 平台的极简、灵活的 Web 开发框架,属于后端 (Node.js) 框架,专注于处理 HTTP 请求、构建 Web 服务器 / API 接口,是 Node.js 生态中最主流的 Web 框架之一。

1.快速入门

1
npm i express		//下载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//快速入门
//1.引入
const express = require('express')

//2.创建
const app = express()

//3.创建路由
app.get('/',(req,resp) => {
resp.end('hello')
})

//监听端口
app.listen(9000,() => {
console.log("服务启动")
})

2.路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
app.<method>(path,callback)			如: get post all等


//创建路由
app.get('/',(res,resp) => {
resp.header('content-type',"text/html;charset=utf-8")
resp.end('首页')
})

app.get("/home",(res,resp) => {
resp.header('content-type',"text/html;charset=utf-8")
resp.end('首页')
})

app.post('/me',(res,resp) => {
resp.header('content-type',"text/html;charset=utf-8")
resp.end('我的')
})

//表示全部方法都行
app.all('/text',(res,resp) => {
resp.end('test test')
})

3.请求头参数获取

请求对象(Request - req)常用操作

操作 说明
req.method 获取HTTP请求方法(GET、POST等)
req.url / req.originalUrl 获取请求URL
req.path 获取请求路径(不包含查询字符串)
req.query 获取查询字符串参数(解析为对象)
req.params 获取路由参数(如 /users/:id 中的id)
req.body 获取请求体数据(需要body-parser中间件)
req.headers 获取请求头对象
req.get('header-name') 获取特定请求头的值
req.cookies 获取cookies(需要cookie-parser中间件)
req.ip 获取客户端IP地址
req.hostname 获取主机名
req.protocol 获取协议(http或https)
req.secure 检查是否为HTTPS请求
req.xhr 检查是否为AJAX请求

Express中req.get()方法可以获取的全部请求头字段,这些字段对应HTTP标准请求头:

字段名 说明 示例值
‘cookie’ 客户端Cookie
'host' 服务器域名和端口 localhost:3000
'user-agent' 客户端信息 Mozilla/5.0...
'accept' 可接受的MIME类型 application/json, text/plain
'accept-encoding' 可接受的内容编码 gzip, deflate, br
'accept-language' 可接受的语言 zh-CN,zh;q=0.9
'connection' 连接控制 keep-alive, close
'content-length' 请求体长度 348
'content-type' 请求体的MIME类型 application/json
'cache-control' 缓存控制指令 no-cache
'pragma' 兼容HTTP/1.0的缓存控制 no-cache
'authorization' 认证凭证 Bearer eyJhbGciOi...

4.响应体参数设置

响应对象(Response - res)常用操作

操作 说明
res.status(code) 设置HTTP状态码
res.set('header', value) 设置响应头
res.cookie(name, value, options) 设置cookie
res.clearCookie(name) 清除cookie
res.send(body) 发送响应(自动设置Content-Type)
res.json(data) 发送JSON响应
res.sendFile(path) 发送文件
res.download(path, filename) 下载文件
res.redirect(status, url) 重定向到指定URL
res.render(view, locals) 渲染模板视图
res.end() 结束响应(不发送数据)
res.type(type) 设置Content-Type
res.location(url) 设置Location头

5.应用对象(Application - app)常用操作

操作 说明
app.use([path], middleware) 使用中间件
app.get(path, handler) 处理GET请求
app.post(path, handler) 处理POST请求
app.put(path, handler) 处理PUT请求
app.delete(path, handler) 处理DELETE请求
app.all(path, handler) 处理所有HTTP方法
app.route(path) 创建链式路由
app.set(name, value) 设置应用设置
app.get(name) 获取应用设置
app.listen(port, callback) 启动服务器
app.engine(ext, callback) 注册模板引擎
app.locals 应用级局部变量
app.use(express.static(dir)) 托管静态文件

6.路由参数设置

如果每个商品点击都有详情页,怎么办? 使用 /: 任意字符 即可

1
2
3
4
5
6
//如果每一个商品点击都会跳出详情页,怎么办????      使用 /:id			注:这里不一定是id  可以是任意字母!!!!!!
app.get('/:id.html',(res,resp) => { //此时只要是.html的页面都会在这里
console.log(res.params.id); //获取id号

resp.end('hello express')
})

7.中间件概述

类似于filter,请求先经过中间件!!!

代码: app.use(函数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//自定义中间件函数,参数需要: req,resp,next
function record(res,resp,next){
let {url,ip} = res
//调用next()进行下一步
next()
}

//使用 此时所有请求必须执行这个!!!!
app.use(record)

//创建路由
app.get('/home',(res,resp) => {
resp.send('首页')
})

app.get("/admin",(req,resp) => {
resp.send('后台管理')
})

//特殊写法
app.get('/me',record,(res,resp) => {}) //可以将中间件放到get、post等函数里面!!

静态资源加载

代码: app.use(express.static(静态资源目录))

1
2
3
4
5
6
7
8
9
10
11
12
const express = require('express')

//创建应用对象
const app = express()

app.use(express.static(__dirname + '/public')) //将静态资源放入这里,即可操作 此时访问只需要 输入文件名即可
//注:框架会自动寻找 index.html 文件!!!

//创建路由
app.get('/home',(res,resp) => {
resp.end('hello express')
})

8.获取请求体内容

可以使用其他包(已弃用): body-parser 或使用内置的!!!(Express 4.16+)

参数:
app.use(express.json()); // 解析 JSON 格式请求体;
app.use(express.urlencoded({ extended: false })); // 解析表单格式请求体(extended: false 用内置查询字符串解析)
此时使用: req.body 可以获取全部参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const express = require('express')

const app = express()

// 【核心】注册内置请求体解析中间件(必须写在路由前面)
app.use(express.json()); // 解析 JSON 格式请求体
app.use(express.urlencoded({ extended: false })); // 解析表单格式请求体(extended: false 用内置查询字符串解析)

//创建
app.get('/login',(req,resp) => {
resp.sendFile(__dirname + '/11_form.html')
})

app.post('/login',(req,resp) => {
console.log(req.body); //{ username: '21323', password: 'dsdsdsd' }
resp.send("获取用户数据成功")
})


app.listen(9000,() => {
console.log("服务启动成功");
})

9.防盗链

什么是防盗链??防止其他人盗用本站的资源,如图片、视频等!!!!
如何实现?? 在请求头里面的Referer 键里面的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
app.use((req,resp,next) => {        
const ref = req.get('referer') //http://127.0.0.1:9000/ 我们只允许这个地址使用
if(ref){
const url = new URL(ref)
//获取host
let hostname = url.hostname
console.log(hostname);
if(hostname != '127.0.0.1'){
resp.status(404).send('错误')
}
}

next()
})

10.路由模块化

当需求变多,此时需要的路由越来越多,如何将这些路由放到一个模块里???
使用: experss.Router()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//1.创建routes文件夹
const express = require('express')

const router = express.Router()

router.get('/admin',(res,resp) => {
resp.send('管理员')
})


router.get('/setting',(res,resp) => {
resp.send("后台设置")
})

module.exports = router //导出



//2.引入
const express = require('express')
const homeRoute = require('./routes/homeRoute.js')
//创建应用对象
const app = express()

//3.使用路由
app.use(homeRoute)

//监听端口
app.listen(9000,() => {
console.log('端口启动');
})

11.模板引擎

下载: npm i ejs
值渲染: ejs.render(字符串,{值,…}) 会读取文件带有 <%= 值%> 的符号
1
2
3
4
5
6
7
8
9
10
11
12
基本读取:
<!-- 转义输出(默认安全) -->
<%= variable %>

<!-- 非转义输出(输出HTML) -->
<%- htmlContent %>

<!-- JavaScript代码 -->
<% JavaScript代码 %>

<!-- 注释(不会输出到HTML) -->
<%# 这是注释 %>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//1,创建一个js文件
//导入
const ejs = require('ejs')
const fs= require('fs') //用于读取html文件

//字符串 需要渲染的值
const china = "中国"
const weather = "天气"

//读取html文件,进行渲染
const str = fs.readFileSync('./1.html').toString()

//进行渲染
const result = ejs.render(str,{china: china,weather}) //如果变量名相同,可以省略 :

console.log(result);

1
2
3
4
5
6
7
8
9
10
11
12
13
#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>
<h2>我爱你 <%= china %></h2> <!-- 值渲染 -->
<h2>当前 <%= weather %></h2>
</body>
</html>
列表渲染
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!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>
<%xiyou.forEach(item => { %> <!--在html写入js代码(<% %>), item为列表的参数(<%= %>),写法和jsp相似!!!!-->
<li><%= item %><li>
<% }) %>
</ul>
</body>
</html>

js代码:
const ejs = require('ejs')
const fs = require('fs')

const xiyou = ['唐僧','猪八戒','沙僧','猴哥']

const str = fs.readFileSync("./2.列表渲染.html").toString()

let result = ejs.render(str,{xiyou: xiyou})

console.log(result);
条件渲染
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!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>
<h2>
<% if(isLogin){ %> //嵌套js语法进行判断
<span>欢迎回来</span>
<% }else{ %>
<button>登录</button>
<% } %>
</h2>
</body>
</html>
在express使用ejs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
app.set('view engine','ejs')		//使用ejs
app.set('view',path.resolve(__dirname,"./views")) //将所有模板文件放到views文件里
app.get('/',(req,resp) => {
//变量
let title = "学前端,好就业"
resp.render('index',{title}) //这里使用resp.render('文件名',{变量}) //这里直接写文件名,后缀必须为ejs!!!!
})


//创建index.ejs文件
<!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>
<h2><%= title %></h2>
</body>
</html>

12.express脚手架

一键生成express项目框架
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
npm i -g express-generator  //全局安装
express -e 文件名 //创建框架

//此时显示
PS E:\frontend\node.js\代码\Express\模板引擎> express -e expressGenerator

warning: option `--ejs' has been renamed to `--view=ejs'


create : expressGenerator\
create : expressGenerator\public\
create : expressGenerator\public\javascripts\
create : expressGenerator\public\images\
create : expressGenerator\public\stylesheets\
create : expressGenerator\public\stylesheets\style.css
create : expressGenerator\routes\
create : expressGenerator\routes\index.js
create : expressGenerator\routes\users.js
create : expressGenerator\views\
create : expressGenerator\views\error.ejs
create : expressGenerator\views\index.ejs
create : expressGenerator\app.js
create : expressGenerator\package.json
create : expressGenerator\bin\
create : expressGenerator\bin\www

change directory:
> cd expressGenerator

install dependencies:
> npm install

run the app:
> SET DEBUG=expressgenerator:* & npm start


再次输入: npm i //安装所有相关依赖

13.查看文件上传报文

enctype=”multipart/form-data” 文件上传必须使用!!!!
1
2
3
4
5
<form action="/portarit" method="post" enctype="multipart/form-data">
<input type="text" name="username"> <br>
头像: <input type="file" name="files"> <br>
<input type="submit" value="提交">
</form>

十、Mongodb

MongoDB 是一款开源的文档型非关系型数据库(NoSQL),由 MongoDB Inc. 开发,采用 C++ 编写。它摒弃了传统关系型数据库的表结构和 SQL 语法,以BSON(类 JSON 的二进制数据格式) 为数据存储格式,主打灵活的文档模型、高可扩展性和高性能,广泛应用于大数据、实时应用、微服务等场景。

下载地址: https://www.mongodb.com/try/download/community

操作:

命令分类 命令语法 说明
启动服务 mongod 本地启动 MongoDB,默认端口 27017,数据目录 /data/db
启动服务 mongod --dbpath <路径> --port <端口> 指定数据目录和端口启动
启动副本集 mongod --replSet <副本集名> --dbpath <路径> --port <端口> 以副本集模式启动
连接实例 mongosh 连接本地默认 MongoDB 实例
连接实例 mongosh --host <IP> --port <端口> 连接指定主机和端口的实例
连接并指定库 mongosh mongodb://<IP>:<端口>/<数据库名> 连接时直接指定数据库
带密码连接 mongosh -u <用户名> -p <密码> --authenticationDatabase <认证库> 带用户密码连接(通常认证库为 admin
退出连接 exitCtrl+C 退出 mongosh 终端

数据库(Database)操作

命令分类 命令语法 说明
查看所有数据库 show dbs 显示有数据的数据库(空数据库不显示)
切换 / 创建数据库 use <数据库名> 切换到指定数据库,若不存在则插入数据时自动创建
查看当前数据库 db 返回当前所在数据库名称
删除当前数据库 db.dropDatabase() 删除当前数据库及所有集合(谨慎使用)
数据库状态 db.stats() 查看数据库的存储大小、文档数等统计信息

集合(Collection)操作

命令分类 命令语法 说明
查看所有集合 show collections / show tables 显示当前数据库的所有集合
创建集合 db.createCollection("<集合名>") 普通创建集合(插入数据时也会自动创建)
创建固定集合 db.createCollection("<集合名>", { capped: true, size: <字节>, max: <文档数> }) 创建固定大小的集合,size 为集合大小,max 为最大文档数
删除集合 db.<集合名>.drop() 删除指定集合
重命名集合 db.<原集合名>.renameCollection("<新集合名>") 将集合重命名

文档(Document)操作

4.1 插入文档

命令分类 命令语法 说明
插入单条 db.<集合名>.insertOne({ <字段>: <值> }) 插入单条文档(3.2+ 推荐)
插入多条 db.<集合名>.insertMany([{ <字段>: <值> }, { <字段>: <值> }]) 插入多条文档(3.2+ 推荐)
兼容插入 db.<集合名>.insert({ <字段>: <值> }) / db.<集合名>.insert([{...}, {...}]) 兼容旧版,可单条 / 多条插入

4.2 查询文档

命令分类 命令语法 说明
查询所有 db.<集合名>.find() 显示所有文档(默认前 20 条,输入 it 看后续)
格式化查询 db.<集合名>.find().pretty() 格式化输出查询结果,更易读
条件查询 db.<集合名>.find({ <字段>: <值> }) 等于条件查询
多条件且查询 db.<集合名>.find({ <字段1>: <值1>, <字段2>: <值2> }) 多个条件同时满足
范围查询 db.<集合名>.find({ <字段>: { $gt: <值>, $lt: <值> } }) $gt(大于)、$lt(小于)、$gte(大于等于)、$lte(小于等于)
包含查询 db.<集合名>.find({ <字段>: { $in: [<值1>, <值2>] } }) $in(在数组中)、$nin(不在数组中)
数组查询 db.<集合名>.find({ <数组字段>: <元素值> }) 查询数组包含指定元素的文档
嵌套文档查询 db.<集合名>.find({ "<嵌套字段.子字段>": <值> }) 查询嵌套文档的字段值
投影查询 db.<集合名>.find({ <条件> }, { <字段1>: 1, <字段2>: 0 }) 1 显示字段,0 隐藏字段(_id 默认为 1)
排序 db.<集合名>.find().sort({ <字段>: 1/-1 }) 1 升序,-1 降序
分页 db.<集合名>.find().skip(<跳过数>).limit(<返回数>) skip 跳过文档,limit 限制返回数量
计数 db.<集合名>.countDocuments({ <条件> }) 统计符合条件的文档数
正则查询 db.<集合名>.find({ <字段>: /<正则表达式>/ }) 模糊匹配,如 /张/ 匹配包含 “张” 的字段值
存在性查询 db.<集合名>.find({ <字段>: { $exists: true/false } }) 判断字段是否存在

4.3 更新文档

命令分类 命令语法 说明
更新单条 db.<集合名>.updateOne({ <条件> }, { $set: { <字段>: <值> } }) 只更新第一条匹配的文档
更新多条 db.<集合名>.updateMany({ <条件> }, { $set: { <字段>: <值> } }) 更新所有匹配的文档
替换文档 db.<集合名>.replaceOne({ <条件> }, { <新文档> }) 覆盖整个文档(保留 _id
自增字段 db.<集合名>.updateOne({ <条件> }, { $inc: { <字段>: <步长> } }) 字段值自增 / 自减(步长为负数则自减)
数组添加元素 db.<集合名>.updateOne({ <条件> }, { $push: { <数组字段>: <元素> } }) 向数组字段添加元素
数组删除元素 db.<集合名>.updateOne({ <条件> }, { $pull: { <数组字段>: <元素> } }) 从数组字段删除指定元素

4.4 删除文档

命令分类 命令语法 说明
删除单条 db.<集合名>.deleteOne({ <条件> }) 删除第一条匹配的文档
删除多条 db.<集合名>.deleteMany({ <条件> }) 删除所有匹配的文档
清空集合 db.<集合名>.deleteMany({}) 删除集合所有文档(保留集合结构,效率低于 drop

十一、会话设置

其他操作:

选项 类型 说明
maxAge 数字 Cookie 有效期(毫秒),如 1000 * 60 * 60 表示 1 小时
expires Date Cookie 过期时间(绝对时间),优先级低于 maxAge
path 字符串 Cookie 生效的路径,默认 /(全站生效)
domain 字符串 Cookie 生效的域名,如 .example.com(子域名也生效)
secure 布尔值 若为 true,仅在 HTTPS 协议下传输 Cookie
httpOnly 布尔值 若为 true,Cookie 无法被 JavaScript(如 document.cookie)读取,防止 XSS 攻击
signed 布尔值 若为 true,生成签名 Cookie,需配合 cookie-parser(secret) 使用
sameSite 字符串 / 布尔值 限制 Cookie 的跨域发送,可选 strict/lax/none,防止 CSRF 攻击
1
2
resp.clearCookie(值)		//删除cookie
req.get('Cookie') //获取cookie

高级操作

1
2
3
4
5
6
7
8
9
10
11
12
13
const express = require('express');
const cookieParser = require('cookie-parser'); // 引入 cookie-parser
const app = express();


app.use(cookieParser('your-secret-key')); // 若不需要签名 Cookie,可直接写 app.use(cookieParser())

app.get('/get-cookie', (req, res) => {
// 读取普通 Cookie
const username = req.cookies.username;
const age = req.cookies.age;
res.send(`普通 Cookie:username=${username},age=${age}`);
});

2.Session

Express 本身不内置 Session 功能,需借助 express-session 中间件实现

1
2
3
4
5
6
7
8
# 核心 Session 中间件
npm install express-session

# 可选:Redis 存储适配器(生产环境推荐)
npm install connect-redis --save redis@4

# 可选:MongoDB 存储适配器
npm install connect-mongo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
const express = require('express');
const session = require('express-session');
const app = express();

// 配置 Session 中间件
app.use(session({
secret: 'sid', // 必选:签名 Session ID 的密钥(防止篡改)
resave: false, // 强制重新保存 Session(即使未修改),建议设为 false
saveUninitialized: false, // 强制保存未初始化的 Session(新会话但无数据),建议设为 false
cookie: {
maxAge: 1000 * 60 * 60, // Session ID 的 Cookie 有效期(1小时,毫秒)
httpOnly: true, // 禁止前端 JS 读取 Cookie,防止 XSS
secure: false, // 开发环境设为 false(HTTP),生产环境 HTTPS 设为 true
sameSite: 'lax' // 防止 CSRF 攻击
}
}));

// 测试 Session 存储
app.get('/set-session', (req, res) => {
// 向 req.session 中写入数据(自动关联当前用户会话)
req.session.username = 'zhangsan';
req.session.age = 25;
req.session.isLogin = true;
res.send('Session 设置成功');
});

// 测试 Session 读取
app.get('/get-session', (req, res) => {
// 从 req.session 中读取数据
const { username, age, isLogin } = req.session;
res.send({
登录状态: isLogin,
用户名: username,
年龄: age
});
});

//销毁
app.get('/logout', (req, res) => {
req.session.destroy((err) => {
if (err) {
return res.send('退出登录失败');
}
res.send('退出登录成功');
});
});

app.listen(3000, () => {
console.log('服务器运行在 http://localhost:3000');
});

3.Token

在 Web 开发中,Token(令牌) 是一种无状态的身份验证机制,常用于前后端分离、分布式系统的身份校验。与 Session 不同,Token 无需在服务器端存储会话数据(仅需验证 Token 的合法性),更适合跨域、微服务等场景。Express 中实现 Token 认证的核心是生成 Token(如 JWT)、验证 Token解析 Token 数据,以下是详细的实现步骤和核心操作。

1
2
3
4
5
6
7
8
# 生成/验证 JWT
npm install jsonwebtoken

# Express 专属 JWT 验证中间件(可选)
npm install express-jwt

# 若需处理跨域(前后端分离必备)
npm install cors