Node.js (基础使用 以及各种常用的 第三方模块) 使用方法

Node.js

  • 一级目录
    • 二级目录
      • 三级目录
  • 命令
  • Node 中的核心模块
    • path 模块
    • fs 模块
    • querystring 模块
    • http 模块
    • 如何对浏览器的请求作出响应
    • 根据不同的 url 地址处理不同的请求和 不同接口的处理
  • MYSQL 数据库
  • Navicat 的使用
  • SQL 语句(不区分大小写)
    • 数据查询
    • 条件查询
    • 模糊查询
    • 统计查询
    • 查询结果排序
    • 限制查询结果
    • 添加数据
    • 修改(更新)数据
    • 删除数据
  • npm 基础使用
    • 本地模块 (第三方)
    • 演示
    • 全局模块
  • mysql 模块
    • mysql使用步骤
  • 封装 MYSQL
  • Express
    • 构造服务器的步骤
  • 中间件
    • 中间件函数的几种用法
    • 中间件的 语法和特点
  • utility (第三方模块)
  • jsonwebtoken(生成 token)
  • express-jwt(解密 token)
        • 注意:
        • 代码:
  • 修改镜像源
        • nrm 模块(控制镜像源)
  • package.json 文件
  • ES6 降级处理

一级目录

二级目录

三级目录

文档: http://nodejs.cn

命令

在文件根目录打开 node 命令, 可以运行 js 文件, 按 tab 键自动补全路径; 语法: node 02(按tab)/xx/xx.js

语法 作用
node -v 查看版本号
node 进入 node
ctrl+c 退出 node 需要按两次
clear 清空命令(不等于撤销)

Node 中的核心模块

path 模块

文档: http://nodejs.cn/api/path.html

path 是 node 本身提供的 API 是专门用来处理路径的模块

  • 使用方法

    1. 先加加载模块

      const path = require('path')
      
    2. 调用 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

fs 模块

文档: 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('读取文件成功时执行的代码')
      }
    })
    

querystring 模块

处理查询字符串的模块

  • 加载模块

    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 模块

可以使用 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,我是服务器');
})

注意:

  1. 必须按顺序使用上述方法,顺序为:
    1. 设置响应头和状态码(可选res.setHeader()、可选res.setHead()、可选res.statusCode)
    2. 设置响应体(可选res.write())
    3. 做出响应(必选res.end(),因为只有调用了res.end方法,才表示做出响应)
  2. 做出响应(调用res.end方法)之后,不能调用其他方法了。
  3. 如果使用了res.write()方法,则不能再次设置响应头了
  4. res.end()方法,只能响应字符串。

根据不同的 url 地址处理不同的请求和 不同接口的处理

上面已经作出响应了, 我们还可以根据不同的 url 和不同的请求方式, 作出不同的响应

  • req 文档: http://nodejs.cn/api/http.html#http_class_http_incomingmessage

    • req.url 获取请求行中的路径
    • req.method 获取请求行中的请求方法
    • req.headers 获取请求头
  • 代码

    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 数据库

MYSQL 数据库是用来管理存放数据的 用户可以对数据库进行 增删改查可以使用 Navicat 工具来管理数据库

Navicat 的使用

准备工作:

  1. 启动 MYSQL 服务(打开phpstudy,启动MySQL);

  2. 打开 Navicat 软件 创建连接:

Node.js (基础使用 以及各种常用的 第三方模块) 使用方法_第1张图片
Node.js (基础使用 以及各种常用的 第三方模块) 使用方法_第2张图片

3.创建数据库
Node.js (基础使用 以及各种常用的 第三方模块) 使用方法_第3张图片
Node.js (基础使用 以及各种常用的 第三方模块) 使用方法_第4张图片

4.创建数据表:
Node.js (基础使用 以及各种常用的 第三方模块) 使用方法_第5张图片

下面是数据表完成后:

id(不允许重复) name age sex tel
1 王宇 23 13200008888
2 王宇 24 13300008888
3 裴志博 25 18866669999
  • id – 自动递增 – √
  • 最后保存,填表名 student
  • 其他补充点
    • 数据库中的数字类型
      • tinyint -128~127
      • smallint -65535 ~ 65535
      • int -21亿 ~ 21亿
      • bigint 更大
    • 数据库中的字符串类型
      • varchar - 变长字符串类型
      • char - 定长字符串类型
      • text - 很长的字符(65535)
      • longtext - 21亿个字符

SQL 语句(不区分大小写)

数据查询

--基本的查询语法
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

模糊查询

  • %: 代表任意长度(包括0)的任意字符
  • _: 代表1位长度的任意字符
-- 语法: 
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)
  • 使用set里设置新数据的值,没有顺序关系
-- 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 基础使用

npmnode 包(模块)管理工具, 安装 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 数据库. 可以进行增删改查

想要使用 mysql 模块 首先需要安装

# 如果之前没有安装过其他模块, 就需要先初始化
npm init -y
# 下载模块
npm i myspl

mysql使用步骤

一共需要五个步骤

// 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.affectedRows – 受影响的行数
    • result.insertId – 新增数据id
  • 修改语句
    • result – 对象
    • result.affectedRows – 受影响的行数(满足条件的)
    • result.changedRows – 被改变的行数
  • 删除语句
    • result – 对象
    • result.affectedRows – 受影响的行数

封装 MYSQL

使用 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

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() 应该注意:

  • 响应的内容不能为数字
  • 如果响应的是JS对象,那么方法内部会自动将对象转成JSON格式。
  • 如果已经做出响应了,就不要再次做出响应了。

中间件

中间件原理:
Node.js (基础使用 以及各种常用的 第三方模块) 使用方法_第6张图片

中间件函数的几种用法

// 下面的中间件,只为当前接口 /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', 中间件函数);

中间件分类:

  • 应用级别的中间件
  • 路由级别的中间件
  • 错误处理中间件
  • 内置中间件(express自带的,比如 express.urlencoded())
  • 第三方中间件(比如multer、express-jwt、express-session、…)

中间件的 语法和特点

特点:

  • 在 js 代码中, 所有的 req和res 是一个对象. 所有的中间件函数 共享
  • 在中间件函数中不调用 next() , 程序执行到当前中间件函数后, 不在向后执行, 为了防止代码逻辑混乱, 调用 next() 后不要再写额外的代码
  • 有可能因为中间件函数顺序的原因, 某一个中间件函数不会执行
  • 使用 app.use() 注册的中间件, GET,POST 请求都可以触发
  • 错误处理中间件, 必须传递 err, req, res, next 四个参数, 而且要放到所有接口的后面.
  • 如果前面的中间件没有给 next 传参, 并且代码也没有错误, 请求就不会进入到错误处理中间件
  • 如果前面的中间件, 为 next 传递了实参, 程序会绕过后面所有的中间件, 直接进入到最后的错误处理中间件

语法:

  • 中间件函数有四个基本的参数, err, req, res, next
  • 如果带有 err 参数, 并且函数处理中间件有四个参数, 那么这个表示 错误处理中间件
    • req 就是请求相关的对象
    • res 就是响应相关的对象
    • next 他是一个函数 在不使用的时候可以省略(除了错误处理中间件)
  • 班写好的中间函数,传递给 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) => {
  
})

utility (第三方模块)

作用: 在实际开发中, 不允许数据表中存在明文密码所以要对密码进行 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: '注册成功' })
        }
    })
});

jsonwebtoken(生成 token)

文档: 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: '账号或密码错误' });
            }
        }
    });
});

express-jwt(解密 token)

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 模块(控制镜像源)

  • nrm 是一个全局的模块 使用前需要安装 (npm i nrm -g)
    • nrm ls 查看的=可用的镜像源
    • nrm use taobaO 切换镜像源(国内一般使用淘宝)
  • 如果 nrm 安装不上
    • 直接使用命令修改镜像源为淘宝
    • npm config set registry https://registry.npm.taobao.org
    • 淘宝会间隔十分钟更新一次 npm 主站上的模块

package.json 文件

  • 执行 npm init -y 初始化之后, 会自动生成这个文件
    • 文件夹不能是中文的, 否则会初始化失败
    • 文件夹名, 不要和我们准备安装的模块重名, 比如 mysql, experess
  • dependencies 翻译过来是依赖的意思。
    • 每次安装第三方模块都会在这里记录
    • 如果你的 node_modules 文件夹删除了, 直接执行npm i 可以把依赖中记录的模块全部安装

ES6 降级处理

因为 ES6 有六蓝旗件如问题, 可以使用一些工具进行降级处理 如:babel

使用步骤

  1. 项目初始化 npm init -y

  2. 在命行中, 安装 babel 官网连接: https://babeljs.io

    npm install  @babel/core @babel/cli @babel/preset-env
    
  3. 配置文件 .babelrc (这个文件需要手工创建)

    // babel 的降级处理配置
    {
      "presets": ["@babel/preset-env"]
    }
    
  4. 在命令中, 运行

    // 把转换的结果输出到指定的文件(如果没有系统自动创建)
    npx babel index.js(原文件) -o indes1.js(转换后的文件)
    // 把转换的结果输出到指定的目录
    npx babel 包含有 js 的目录 -d 转换后的目录
    

你可能感兴趣的:(总结,node.js,mysql,前端,中间件)