文档: http://nodejs.cn
在文件根目录打开 node 命令, 可以运行 js 文件, 按 tab 键自动补全路径; 语法: node 02(按tab)/xx/xx.js
语法 | 作用 |
---|---|
node -v | 查看版本号 |
node | 进入 node |
ctrl+c | 退出 node 需要按两次 |
clear | 清空命令(不等于撤销) |
文档: http://nodejs.cn/api/path.html
path
是 node 本身提供的 API 是专门用来处理路径的模块
使用方法
先加加载模块
const path = require('path')
调用 path
中的方法来处理问题
方法 | 作用 | 效果 |
---|---|---|
console.log(__dirname) | 查看当前文件的绝对路径 | E:\xx\当前文件 |
path.join(‘a’, ‘b’, ‘c’) | 智能拼接路径 | a/b/c |
path.join(’__dirname’, ‘b’, ‘c’) | 将绝对路径和智能拼接路径结合起来 | E:\xx\b\c |
path.extname(‘index.html’) | 获取文件后缀 | .html |
文档: http://nodejs.cn/api/fs.html
fs(文件系统) 是对 文件/文件夹 的操作
使用方法
先加载模块
const fs = require('fs')
调用 fs 模块的方法来处理问题
方法 | 作用 |
---|---|
fs.access(‘path’, callback(err)) | 判断路径是否存在 |
fs.appendFile(file, data, callback) | 向文件中追加内容 |
fs.copyFile(src, callback) | 复制文件 |
fs.mkdir(‘path’, callback) | 创建目录 |
fs.readFile(‘path’, callback(err, data)) | 异步读取文件 |
fs.watchFile(‘path’, ‘内容’, callback(err)) | 异步写入文件 |
例
fs.readFile('./text.html', 'utf-8', (err, data) => {
if(err) {
// 读取如果没有发生错误 err = null, 有错误 err = {错误对象}
// data 表示读取到的结果
console.log('读取出错是执行的代码')
} else {
console.log(data)
console.log('读取文件成功时执行的代码')
}
})
处理查询字符串的模块
加载模块
const querystring = require('querystring')
调用 querystring 中的模块
方法 | 作用 | 效果 |
---|---|---|
querystring.parse(‘id=1&name=zs&age=20’) | 将查询字符串解析成 js 对象 | { id: ‘1’, name: ‘zs’, age: ‘20’ } |
querystring.stringify({ id: ‘1’, name: ‘zs’, age: ‘20’ }) | 将 js 对象转成查询字符串 | id=1&name=zs&age=20 |
可以使用 http 模块来自己搭建 wed 服务器 ( ↓ 是步骤)
加载 http 模块
const http = require('http')
创建服务对象(服务器), 一般命名为 server
const server = http.createServer()
给服务器(server) 对象, 注册请求(request) 事件, 监听浏览器的请求
server.on('request', () => {
// 只要有浏览器的请求,就会触发该事件
console.log('我发现你的请求了,但是不想搭理你');
})
设置端口,开启服务
server.listen(3000, () => {
console.log('服务器启动了');
})
监听浏览器的请求。只要有浏览器的请求,就会触发下面的事件
server.on('request', (req, res) => {
// req:request,请求;它是一个对象;它包含了所有和请求相关的信息
// res:response,响应;它是一个对象;它包含了所有和响应相关的信息
/* res.end('响应的内容'); --- 它可以设置响应体,并做出响应
* res.setHeader(); --- 设置响应头
* res.write('响应体'); -- 设置响应体,但不会做出响应
* res.writeHead() -- 设置响应头,设置响应状态码
* res.statusCode = 404; ---- 设置响应状态码 */
// res.statusCode = 404;
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.end('hello,我是服务器');
})
注意:
上面已经作出响应了, 我们还可以根据不同的 url 和不同的请求方式, 作出不同的响应
req 文档: http://nodejs.cn/api/http.html#http_class_http_incomingmessage
代码
server.on('request', (req, res) => {
// 如果浏览器请求的是 /my/userinfo 接口 请求方式是 GET
if (req.url === '/my/userinfo' && req.method === 'GET') {
/* GET 接口 */
res.end(Date.now())
// 说明浏览器请求的是 /api/login 接口 请求方式是 POST
} else if (req.url === '/api/login' && req.method === 'POST') {
/* POST 接口*/
// 1. 创建一个空的字符串, 用于保存提交过来的数据
let str = ''
// 2. 为 req 注册 data 事件, 只要有数据提交过来就会触发, 当数据较大时是分块接收的
req.on('data', (chunk) => {
// chunk -- 块
str += chunk;
})
// 3. 为 req 注册 data 事件, 当完全接收了提交过来的数据后就会触发
req.on('end', () => {
console.log(str); // id=1&name=zs&age=43
})
} else {
// 请求了一个不存在的接口,响应404,表示没有找到
}
MYSQL 数据库是用来管理存放数据的 用户可以对数据库进行 增删改查可以使用 Navicat 工具来管理数据库
准备工作:
启动 MYSQL 服务(打开phpstudy,启动MySQL);
打开 Navicat 软件 创建连接:
下面是数据表完成后:
id(不允许重复) | name | age | sex | tel |
---|---|---|---|---|
1 | 王宇 | 23 | 男 | 13200008888 |
2 | 王宇 | 24 | 男 | 13300008888 |
3 | 裴志博 | 25 | 男 | 18866669999 |
student
。--基本的查询语法
select 字段,字段,.... from 表名
--查询所有的字段
select * from 表名
-- 查询id小于10的学生
select * from student where id<10
-- 查询id小于20的女学生
select * from student where id<20 and sex='女'
-- 查询年龄大于等于20小于等于30的学生
select * from student where age>=20 and age<=30
--语法:
select * from 表名 where 条件
-- 查询id小于10的学生
select * from student where id<10
-- 查询id小于20的女学生
select * from student where id<20 and sex='女'
-- 查询年龄大于等于20小于等于30的学生
select * from student where age>=20 and age<=30
-- 语法:
select * from 表名 where 字段 like '%关键字%'
-- 查询名字中带有飞的
select * from student where username like '%飞%'
-- 查询名字的最后一个字是祥的
select * from student where username like '%祥'
-- 查询最大的年龄
select max(age) from student
-- 查询最小的年龄
select min(age) from student
-- 查询年龄的平均值
select avg(age) from student
-- 查询年龄的总和(所有人的年龄加到一起)
select sum(age) from student
-- 重点:查询总记录数(一共有多少条数据)
select count(*) from student
-- 可以为查询到的字段定义别名
select count(*) 别名 from student
-- 语法:
select * from 表名 order by 字段 asc(升序)/desc(降序)
-- 查询所有的学生,按年龄降序排序
select * from student order by age desc
-- 查询所有的男同学,并按年龄降序排序
select * from student where sex='男' order by age desc
注意:如果SQL语句中,有where和order by,where一定要放到order by之前
-- 语法:
select * from 表名 limit 起始位置, 长度
-- 查询所有学生中的第1、2、3个
select * from student limit 0, 3
注意:where、order by、limit如果一起使用,是有顺序的,where在最前面、其次是order by、limit要放到最后。另外三者之间没有and之类的
-- 语法:
insert into student (字段, 字段, ...) values (值, 值, ...)
insert into student (username, age, sex) values ('虚空恐惧', 98, '男')
insert into heroes values (null, '拉克丝', '光辉女郎', '女', 28)
-- insert into 表名 set 字段=值, 字段=值, ....
insert into student set age=30, sex='男', username='李青'
-- 语法
update 表名 set 字段1=值1, 字段2=值2,... where 修改条件
update student set age=20, sex='女' where id=11
不指定条件会修改所有的数据
-- 语法
delete from 表名 where 删除条件
delete from student where id=11
不指定条件将删除所有的数据
npm
是 node
包(模块)管理工具, 安装 node
时自动安装的.
作用: 1. 下载并安装第三方的模块
2. 卸载第三方模块
3. 发布模块
4. 删除已发布的模块
本地模块: 只能在 当前文件夹和当前文件夹的子文件夹中 使用
下载安装第三方模块
npm install 模块名
# 简写
npm i 模块名
卸载模块
npm uninstall 模块名
# 简写
npm un 模块名
// 加载模块
const path = require('path')
// 调用模块的方法完成功能
path.join()
全局安装的模块, 不能通过 require()
加载使用, 一般都是命令或者工具
全局安装的模块, 安装在 c 盘, 通过npm root -g
可以查看全局安装路径
下载安装模块(多了一个 -g
)
npm i 模块名 -g
# 或
npm i -g 模块名
# mac 系统如果安装不上,使用下面的命令提高权限
sudo npm i -g 模块名
卸载命令(多一个 -g
)
npm un 模块名 -g
##全局安装 nodemon 模块
安装命令
npm i nodemon -g
作用: 代替 node 启动服务器, 当执行 nodmon 文件名
之后会自动重启服务
管理员
方式,打开命令行窗口
执行 set-ExecutionPolicy RemoteSigned;
在出现的选项中,输入 A
,回车。即可
mysql
是一个第三方模块, 专门用来操作 MYSQL 数据库. 可以进行增删改查
想要使用 mysql
模块 首先需要安装
# 如果之前没有安装过其他模块, 就需要先初始化
npm init -y
# 下载模块
npm i myspl
一共需要五个步骤
// 1. 加载 mysql 模块
const mysql = require('mysql')
// 2. 创建连接对象(连接数据库) 设置连接参数(填写账号密码)
const conn = mysql.createConnection({
// 属性: 值
host: 'localhost',
port: 3306, // navict 和数据库之间连接的端口, 代码操作时也可以不写?
user: 'root',
password: '密码',
database: '(数据)库名'
})
// 3. 连接到 mysql 服务器
conn.connect()
// 4. 完成查询 (增删改查)
// sql 语句= select * from student limit ?
conn.query(SQL语句, [SQL 中占位符的值], (err, result, fields) => {
// err: 错误信息
// result: 查询结果
// fields: 当前查询过程中涉及到的字段信息,一般用不着
})
// 5. 关闭连接, 释放资源
conn.end()
result的 主要属性以及返回的数据类型 如下:
result
– 数组result
– 对象result
– 对象result
– 对象使用 mysql 一般都需要封装(用形参传值)用的时候直接调用函数就好
function abc(sql, params, callback) {
const mysql = require('mysql');
const conn = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '12345678',
database: 'hahaha'
});
conn.connect();
// 完成增删改查
conn.query(sql, params, callback);
conn.end();
}
// 导出(一定要导出否则此工具被当做模块加载后无法使用)
module.exports = abc;
Express: 是一个基于 node 的第三方模块, 用于快速搭建服务器
注: 在使用 express 的时候仍然可以使用 http 模块的方法
文档: 官网: http://expressjs.com
中文文档(非官方): http://www.expressjs.com.cn
腾讯云开发者手册: https://cloud.tencent.com/developer/doc/1079
// 使用express 搭建web服务器
// 1) 加载 express 模块
const express = require('express')
// 2) 创建 express 服务器
const app = express()
// 3) 开启服务器
app.listen(3006, () => console.log('express服务器开始工作了'))
// 4) 加载封装的 mysql 工具
const abc = require('abc')
// 4) 监听浏览器请求并进行处理
app.get('GET请求的地址', (req, res) => {
abc.('sql 语句', [传值], (err, result) => {
// 查询失败返回 err
if(err) throw err
// 查询成功将 设置的内容和结果 响应给客户端
res.send({
status: 0,
message: 'xx',
data: result
})
})
})
app.post('POST请求的地址', 处理函数)
res.send() 方法可以替换 res.end() 对服务器做出响应
使用 res.send() 应该注意:
// 下面的中间件,只为当前接口 /my/userinfo 这个接口服务
app.get('/my/userinfo', 中间件函数);
app.get('/api/login', 中间件函数, 中间件函数, 中间件函数, 中间件函数 .....);
// 下面的几个中间件,是处理 /api/login 接口的
app.post('/api/login', 中间件函数)
app.post('/api/login', 中间件函数, 中间件函数, 中间件函数, 中间件函数 .....);
// app.use 中的中间件,可以处理所有的GET请求和所有的POST请求,没有指定路径,那么处理所有接口
app.use(中间件函数);
app.use(中间件函数, 中间件函数, 中间件函数 .....);
// 下面的中间件函数,只处理 /api 开头的接口
app.use('/api', 中间件函数);
// 下面的中间件函数,处理 /abcd 、 /abd 这两个接口
// ? 代表 c 可以有也可以没有
app.get('/abc?d', 中间件函数);
app.post('/abc?d', 中间件函数);
app.use('/abc?d', 中间件函数);
中间件分类:
特点:
next()
, 程序执行到当前中间件函数后, 不在向后执行, 为了防止代码逻辑混乱, 调用 next()
后不要再写额外的代码app.use()
注册的中间件, GET,POST 请求都可以触发语法:
app.get()
、app.post()
、或app.use()
使用// 第一个中间件
app.use((req, res, next) => {
req.aa = '123';
next();
})
// 第二个中间件(只处理以 /api 开头的接口)
app.use('/api', (req, res, next) => {
req.bb = '456';
next();
})
// 第三个中间件(只处理以 /my 开头的接口)
app.use('/my', (req, res, next) => {
req.cc = '789';
next();
})
// 下面接口中的三个中间件,只能 /api/test 这个请求
app.get('/api/test', (req, res, next)=>{
next();
}, (req, res, next)=>{
next();
}, (req, res) => {
console.log(req.aa, req.bb, req.cc)
res.send('hello');
})
// 错误处理中间件
app.use((err, req, res ,next) => {
})
作用: 在实际开发中, 不允许数据表中存在明文密码所以要对密码进行 MD5
加密,
修改代码,将密码进行加密处理,然后 再添加到数据库:
+ const utility = require('utility');
router.post('/reguser', (req, res) => {
// 接收账号和密码
// console.log(req.body); // { username: 'laotang', password: '123456' }
+ req.body.password = utils.md5(req.body.password);
db('insert into user set ?', req.body, (err, result) => {
if (err) {
console.log(err.message)
res.send({ status: 1, message: err.message });
} else {
res.send({ status: 0, message: '注册成功' })
}
})
});
文档: https://github.com/auth0/node-jsonwebtoken
语法:
let token = jwt.sign(数据载体, 秘钥, [配置项, 回调函数]);
- 数据载体:必须写成对象形式,用于保存用户信息
- 秘钥:字符串类型,随便填就行。后续解密token的时候,还需要用到它
- 配置项:必须是对象形式,expiresIn表示有效期;
- 回调函数:函数类型,token生成之后触发的一个函数
使用方法:
+ const jwt = require('jsonwebtoken');
router.post('/login', (req, res) => {
// 客户端提交账号密码过来
// 1. 接收账号密码 (req.body)
let username = req.body.username;
let password = utils.md5(req.body.password);
// 2. 判断账号和密码是否正确
db('select * from user where username=? and password=?', [username, password], (err, result) => {
if (err) {
res.send({ status: 1, message: err.message });
} else {
// console.log(result);
if (result.length > 0) {
+ // token前面必须加 Bearer空格,一定要注意空格
+ let token = 'Bearer ' + jwt.sign({ userId:result[0].id}, 'shhhhh', { expiresIn: '2h'})
- res.send({ status: 0, message: '登录成功' })
+ res.send({ status: 0, message: '登录成功', token:token })
} else {
res.send({ status: 1, message: '账号或密码错误' });
}
}
});
});
expresss-jwt 是一个第三方模块
文档: https://github.com/auth0/express-jwt
express
使用的第三方中间件expressJWT()
函数的作用是解密 token 字符串, 将 token 中保存的用户信息, 赋值给 req.user
, secret
的值需要和生成 token 是时填写的秘钥一样, 否则将解密失败unless()
方法的作用是控制那些接口不需要认证// 搭建服务器的三行代码
const express = require('express');
const app = express();
app.listen(3006, () => console.log('启动了'));
+ // 加载 express-jwt 模块
+ const expressJWT = require('express-jwt')
+ // 解密 token
+ app.use(expressJWT({
+ secret: 'shhhhh', // 解密字符串,和加密时的秘钥一样
+ algorithms: ['HS256']
+ }).unless({
+ // 除了登录和注册的接口之外,其他接口都需要认证
+ path: ['/api/login', '/api/reguser']
+ }));
// 配置一下,使用express提供的方法来接收客户端提交的查询字符串;并且把接收到的结果赋值给 req.body
app.use(express.urlencoded({ extended: false }));
// 导入 login 路由对象
app.use('/api', require('./routers/login'));
// 导入category路由对象,注册成中间件
app.use('/my/article', require('./routers/category'));
+ // 错误处理中间件, 如果 token 解密失败时会触发
+ app.use(function (err, req, res, next) {
+ if (err.name === 'UnauthorizedError') {
+ res.status(401).send({ status: 1, message: '身份认证失败!' });
+ }
+ });
镜像网站就是复制的跟别人的网站一模一样(资源), 因为我们安装完 node , 都是从 npm 的主站(主站在海外)上面下载第三方模块,速度较慢
nrm ls
查看的=可用的镜像源nrm use taobaO
切换镜像源(国内一般使用淘宝)npm config set registry https://registry.npm.taobao.org
npm init -y
初始化之后, 会自动生成这个文件
dependencies
翻译过来是依赖的意思。
node_modules
文件夹删除了, 直接执行npm i
可以把依赖中记录的模块全部安装因为 ES6 有六蓝旗件如问题, 可以使用一些工具进行降级处理 如:babel
使用步骤
项目初始化 npm init -y
在命行中, 安装 babel 官网连接: https://babeljs.io
npm install @babel/core @babel/cli @babel/preset-env
配置文件 .babelrc
(这个文件需要手工创建)
// babel 的降级处理配置
{
"presets": ["@babel/preset-env"]
}
在命令中, 运行
// 把转换的结果输出到指定的文件(如果没有系统自动创建)
npx babel index.js(原文件) -o indes1.js(转换后的文件)
// 把转换的结果输出到指定的目录
npx babel 包含有 js 的目录 -d 转换后的目录