node.js - 知识点总结

206 阅读11分钟

常用方法

get客户端传输过来的数据

req.query;

post客户端传输过来的数据

req.query;

终端启动文件

nodemon .\局部生效的中间键.js

1. 导入 express
const express = require('express')
2. 创建路由对象
const router = express.Router()
3. 挂载具体的路由
router.get('/user/list', (req, res) => {
  res.send('Get user list.')
})
router.post('/user/add', (req, res) => {
  res.send('Add new user.')
})
4. 向外导出路由对象
module.exports = router
跨域模块导入并注册到中间件,所有路由之前

const cors = require('cors'); app.use(cors());

解析查询字符串为对象形式,所有路由之前

app.use(express.urlencoded({ extended: false })); const express = require('express');

创建一个路由

const router = express.Router();

router.get('/get', (req, res) => { //获取客户端发送过来的数据 const query = req.query; res.send({ status: 0, msg: 'GET请求成功', data: query, }); }); router.post('/post', (req, res) => { const body = req.body; res.send({ status: 0, msg: 'POST请求成功', data: body, }); });

共享给其他文件module.exports = router;

module.exports = router;

第三方包的安装卸载发布

1.包的初始化

npm init -y  #这里文件夹名字不能有 中文 空格 纯数字

2.安装包

npm i 包名
npm install 包名
npm i  包名@版本号  => npm i jquery@2.22.2

3.安装全局包

npm i 包名 -g

4.卸载包

npm uninstall 包名
npm uninstall 包名@版本号
npm uninstall 包名 -g # 卸载全局包

5.nrm的使用

1. npm i nrm -g # 安装nrm
2. nrm ls # 展示可用的镜像链接
3. nrm use 镜像名字

6.包的发布

1. nrm use npm #切换为官方镜像
2. npm login #登陆输入账号和密码
3. npm  publish #注意终端要在项目的根目录
4. npm  unpublish 包名 --force #删除已发布的包

7. 安装nodemo的使用

npm i nodemon -g

fs 文件系统模块

导入fs模块

const fs = require('fs')

读取指定文件中的内容

⚫ fs.readFile() 方法,用来读取指定文件中的内容

//路径,格式,回调函数(null,读取数据)-成功是null,不成功是报错,不成功数据是未定义
const fs = require('fs');
fs.readFile('./Ahigpjbojz.js', 'utf8', function (err, dataStr) {
  console.log(err);
  console.log(dataStr);
});

向指定的文件中写入内容

⚫ fs.writeFile() 方法,用来向指定的文件中写入内容

// 1. 导入 fs 文件系统模块
const fs = require('fs')

// 2. 调用 fs.writeFile() 方法,写入文件的内容
//    参数1:表示文件的存放路径
//    参数2:表示要写入的内容
//    参数3:回调函数

fs.writeFile('./files/3.txt', 'ok123', function(err) {
  // 2.1 如果文件写入成功,则 err 的值等于 null
  // 2.2 如果文件写入失败,则 err 的值等于一个 错误对象
  // console.log(err)

  if (err) {
    return console.log('文件写入失败!' + err.message)
  }
  console.log('文件写入成功!')
})

path.join() 路径片段

使用 path.join() 方法,可以把多个路径片段拼接为完整的路径字符串:

 const pathStr = path.join('/a', '/b/c', '../../', './d', 'e')
 console.log(pathStr)  // \a\b\d\e

const pathStr2= fs.readFile(__dirname + '/files/1.txt')
console.log(pathStr2)

获取路径中的文件扩展名-后缀

  1. path.extname() 的语法格式

使用 path.extname() 方法,可以获取路径中的扩展名部分,语法格式如下: path.extname(path)

参数解读:

⚫ path 必选参数,表示一个路径的字符串

⚫ 返回: 返回得到的扩展名字符串

路径模块

const path = require('path')

设置响应头解决中文乱码问题

 res.setHeader('Content-Type', 'text/html; charset=utf-8')

创建一个服务器

const http = require('http');
const server = http.createServer();//实例化服务器
//服务器事件,req是路径,res是内容
server.on('request', function (req, res) {
  console.log('Someone visit our web server.');
  res.setHeader('Content-Type', 'text/html; charset=utf-8');
  res.end('哈哈哈');
});
// 4. 启动服务器
server.listen(80, function () {
  console.log('server running at http://127.0.0.1');
});

exports 对象

由于 module.exports 单词写起来比较复杂,为了简化向外共享成员的代码,Node 提供了 exports 对象。默认情况下,exports 和 module.exports 指向同一个对象。最终共享的结果,还是以 module.exports 指向的对象为准 时刻谨记,require() 模块时,得到的永远是 module.exports 指向的对象

第三方包的下载(淘宝镜像.因为境外网速慢,所以使用镜像)

npm config set registry https://registry.npm.taobao.org

包的初始化

npm init -y 初始化 会自动创建一个json文件记录你安装的包, 禁止修改, 因为他是全自动托管的

npm install 包名 安装第三方包 const moment = require('moment') 调用第三方包 const dt = moment().format('YYYY-MM-DD ' + 'HH:mm:ss'); 格式化时间

安装指定版本的包

默认情况下,使用 npm install 命令安装包的时候,会自动安装最新版本的包。如果需要安装指定版本的包,可以在包名之后,通过 @ 符号指定具体的版本,例如:

npm i moment@2.22.2

Express

Express 的中文官网: www.expressjs.com.cn/

安装框架npm i express@4.17.1

创建服务器

//安装框架npm i express@4.17.1
//导入模块
const express = require('express');
//创建服务器
const app = express();
//设置监听
app.get('/user', (req, res) => {
  res.send({ name: '肉丝儿', age: 18, scx: '女' });
});
app.post('/user', (req, res) => {
  res.send('post请求成功');
});
app.listen(3002, function () {
  console.log('http://localhost:3002');
});

动态获取匹配参数

app.get('/delete/:id/:name', (req, res) => {
  res.send(req.params);
});
get发送发送请求
http://localhost:3002/delete/999/jike

终端启动文件

nodemon .\局部生效的中间键.js

路由

Express 中的路由的例子

// 挂载路由
app.get('/', (req, res) => {
  res.send('hello world.')
})
app.post('/', (req, res) => {
  res.send('Post Request.')
})

模块化路由

为了方便对路由进行模块化的管理,Express 不建议将路由直接挂载到app 上,而是推荐将路由抽离为单独的模块。 将路由抽离为单独模块的步骤如下: ① 创建路由模块对应的 .js 文件 ② 调用 express.Router() 函数创建路由对象 ③ 向路由对象上挂载具体的路由 ④ 使用 module.exports 向外共享路由对象 ⑤ 使用 app.use() 函数注册路由模块

创建路由模块

// 1. 导入 express
const express = require('express')
// 2. 创建路由对象
const router = express.Router()

// 3. 挂载具体的路由
router.get('/user/list', (req, res) => {
  res.send('Get user list.')
})
router.post('/user/add', (req, res) => {
  res.send('Add new user.')
})

// 4. 向外导出路由对象
module.exports = router

为路由模块添加前缀

类似于托管静态资源时,为静态资源统一挂载访问前缀一样,路由模块添加前缀的方式也非常简单:

// 1. 导入路由模块
const router = require('./03.router')
// 2. 注册路由模块
app.use('/api', router)

中间件

//导入模块
const express = require('express');
//创建服务器
const app = express();
// 必须写到get,post前面
app.use((req, res, next) => {
  res.send('服务器维护中');
  //   next(); //起到开关左右,不写就会导致后面请求不执行
});
//监听事件
app.get('/', (req, res) => {
  res.send('999');
});
//启动服务器
app.listen(80);
console.log('http://localhost');

局部生效的中间件

//导入模块
const express = require('express');
//创建服务器
const app = express();
let mw = (req, res, next) => {
  console.log('局部生效的中间件');
};
//创建路由
app.get('/', mw, (req, res) => {
  res.send('hello');
});
app.get('/po', mw, (req, res) => {
  res.send({ age: 20 });
});
app.listen(80);
console.log('http://localhost');

错误级别的中间件

必须注册在所有路由之后,否则会不能正常工作

//导入模块
const express = require('express');
//创建服务器
const app = express();
app.get('/', (req, res) => {
  throw new Error('服务器内部错误444');
});
//错误级别中间键,发生错误立即跳转本中间件,
//打印错误信息,防止服务器崩溃,写在所有
app.use((err, req, res, next) => {
  console.log(err.message);
  res.send(err.message);
});
app.listen(80);

Express内置的中间件

自 Express 4.16.0 版本开始,Express 内置了 3 个常用的中间件,极大的提高了Express 项目的开发效率和体验: ① express.static快速托管静态资源的内置中间件,例如:HTML 文件、图片、CSS 样式等(无兼容性) ② express.json解析 JSON 格式的请求体数据(有兼容性,仅在4.16.0+ 版本中可用) ③ express.urlencoded 解析 URL-encoded 格式的请求体数据(有兼容性,仅在4.16.0+ 版本中可用)

第三方的中间件

① 运行 npm install body-parser安装中间件 ② 使用 require 导入中间件 ③ 调用 app.use() 注册并使用中间件 注意:Express 内置的 express.urlencoded中间件,就是基于body-parser 这个第三方中间件进一步封装出来的。

Express 中的路由

在 Express 中,路由指的是客户端的请求与服务器处理函数之间的映射关系。 Express 中的路由分3 部分组成,分别是请求的类型、请求的URL 地址、处理函数,

自定义中间件

  1. 需求描述与实现步骤

自己手动模拟一个类似于 express.urlencoded这样的中间件,来解析POST 提交到服务器的表单数据。 实现步骤: ① 定义中间件 ② 监听 req 的 data 事件 ③ 监听 req 的 end 事件 ④ 使用 querystring 模块解析请求体数据 ⑤ 将解析出来的数据对象挂载为 req.body ⑥ 将自定义中间件封装为模块

  1. 定义中间件

使用 app.use() 来定义全局生效的中间件,代码如下:

  1. 监听 req 的 data 事件

有数据传输的时候触发

chunk 块 最开始是一个个代码块,需要拼接

// 1. 定义一个 str 字符串,专门用来存储客户端发送过来的请求体数据
  let str = ''
  // 2. 监听 req 的 data 事件
  req.on('data', (chunk) => {
    str += chunk
  })

4. 监听 req 的 end 事件

数据传输完毕触发

当客户端最终把所有数据发送到服务器之后,会自动触发 req 的 end 事件。 因此,我们可以在req 的 end 事件中,拿到并处理完整的请求体数据。示例代码如下:

req.on('end', () => {
    // 在 str 中存放的是完整的请求体数据
     console.log(str)
})

5. 使用 querystring 模块解析请求体数据

Node.js 内置了一个querystring 模块,专门用来处理查询字符串。通过这个模块提供的 parse() 函数,可以轻松把 查询字符串,解析成对象的格式。示例代码如下:

// 导入 Node.js 内置的 querystring 模块
const qs = require('querystring')

const body = qs.parse(str)

6. 将解析出来的数据对象挂载为 req.body

为了方便在后续的业务处理流程中,能够直接访问当前中间件解析出来的请求体对象,我们将解析出来的数据,挂载 为 req 的自定义属性,命名为req.body。示例代码如下:

    // 3. 监听 req 的 end 事件
      req.on('end', () => {
        // 在 str 中存放的是完整的请求体数据
        // console.log(str)
        // TODO: 把字符串格式的请求体数据,解析成对象格式
        const body = qs.parse(str)
        req.body = body
        next()
      })
  1. 将自定义中间件封装为模块

为了优化代码的结构,我们可以把自定义的中间件函数,封装为独立的模块,示例代码如下:

  // 导入 Node.js 内置的 querystring 模块
    const qs = require('querystring')
    
    const bodyParser = (req, res, next) => {
      // 定义中间件具体的业务逻辑
      // 1. 定义一个 str 字符串,专门用来存储客户端发送过来的

请求体数据

      let str = ''
      // 2. 监听 req 的 data 事件
      req.on('data', (chunk) => {
        str += chunk
      })
      // 3. 监听 req 的 end 事件
      req.on('end', () => {
        // 在 str 中存放的是完整的请求体数据
        // console.log(str)
        // TODO: 把字符串格式的请求体数据,解析成对象格式
        const body = qs.parse(str)
        req.body = body
        next()
      })
    }
    //共享出去
    module.exports = bodyParser

创建一个基本的API POST 借口

const express = require('express');
//创建一个路由
const router = express.Router();

router.get('/get', (req, res) => {
  //获取客户端发送过来的数据
  const query = req.query;
  res.send({
    status: 0,
    msg: 'GET请求成功',
    data: query,
  });
});
router.post('/post', (req, res) => {
  const body = req.body;
  res.send({
    status: 0,
    msg: 'POST请求成功',
    data: body,
  });
});

module.exports = router;
创建启动服务器,导入跨域模块

npm install cors 安装第三方跨域中间件

const express = require('express');
const app = express();
//跨域模块导入并注册到中间件
const cors = require('cors');
app.use(cors());
//解析查询字符串为对象形式
app.use(express.urlencoded({ extended: false }));
const aa = require('./02.apiGET');
app.use('/api', aa);
app.listen(8081);
console.log('http://localhost:8081');

数据库

-- 通过 * 把 users 表中所有的数据查询出来
-- select * from users

-- 从 users 表中把 username 和 password 对应的数据查询出来
-- select username, password from users

-- 向 users 表中,插入新数据,username 的值为 tony stark  password 的值为 098123
-- insert into users (username, password) values ('tony stark', '098123')
-- select * from users

-- 将 id 为 4 的用户密码,更新成 888888
-- update users set password='888888' where id=4
-- select * from users

-- 更新 id 为 2 的用户,把用户密码更新为 admin123  同时,把用户的状态更新为 1
-- update users set password='admin123', status=1 where id=2
-- select * from users

-- 删除 users 表中, id 为 4 的用户
-- delete from users where id=4
-- select * from users

-- 演示 where 子句的使用
-- select * from users where status=1
-- select * from users where id>=2
-- select * from users where username<>'ls'
-- select * from users where username!='ls'

-- 使用 AND 来显示所有状态为0且id小于3的用户
-- select * from users where status=0 and id<3

-- 使用 or 来显示所有状态为1 或 username 为 zs 的用户
-- select * from users where status=1 or username='zs'

-- 对users表中的数据,按照 status 字段进行升序排序
-- select * from users order by status

-- 按照 id 对结果进行降序的排序  desc 表示降序排序   asc 表示升序排序(默认情况下,就是升序排序的)
-- select * from users order by id desc

-- 对 users 表中的数据,先按照 status 进行降序排序,再按照 username 字母的顺序,进行升序的排序
-- select * from users order by status desc, username asc

-- 使用 count(*) 来统计 users 表中,状态为 0 用户的总数量
-- select count(*) from users where status=0

-- 使用 AS 关键字给列起别名
-- select count(*) as total from users where status=0
-- select username as uname, password as upwd from users

SELECT 列名称 示例

获取某一列的所有数据

如需获取名为"username" 和 "password" 的列的内容(从名为 "users" 的数据库表),请使用下面的SELECT 语句:

select username , password from users

INSERT INTO 语句

INSERT INTO 语句用于向数据表中插入新的数据行

  1. INSERT INTO 示例

向 users 表中,插入一条 username 为 tony stark,password为 098123的用户数据,示例如下:

insert into users (username,password) values ('tony stark','098123')

操作数据库的基本使用

where 限定条件

where是限定条件,我们只标记删除id为 ? 的数据,?是你的自定义数据

select * from users where status = 1

select * from users where  id > 2

select * from users where  username <> 'admin'

删除 id 为 4 的数据

从 users 表中,删除 id 为 4 的用户,示例如下

delete from users where id = 4

AND 和 OR 运算符

  1. 语法

AND 和 OR 可在 WHERE 子语句中把两个或多个条件结合起来。 AND 表示必须同时满足多个条件,相当于JavaScript 中的 && 运算符,例如if (a !== 10 && a !== 20) OR 表示只要满足任意一个条件即可,相当于JavaScript 中的 || 运算符,例如if(a !== 10 || a !== 20)

AND 来显示所有 status 为 0,并且 id 小于 3 的

使用 AND 来显示所有 status 为 0,并且 id 小于 3 的用户:

select * from users where status=0 and id < 3

OR 运算符示例

status 为 1,或者 username 为 zs

使用 OR 来显示所有 status 为 1,或者 username 为 zs 的用户:

select * from users where status=1 or username='zs'

ORDER BY 子句 升序 降序 多重排序 函数别名

  1. 语法

ORDER BY 语句用于根据指定的列对结果集进行排序。 ORDER BY 语句默认按照升序对记录进行排序。 如果您希望按照降序对记录进行排序,可以使用DESC 关键字。

  1. ORDER BY 子句 - 升序排序

对 users 表中的数据,按照status 字段进行升序排序,示例如下:

select * from users order by status;
select * from users order by status asc;

3. ORDER BY 子句 – 降序排序

对 users 表中的数据,按照id 字段进行降序排序,示例如下:

select * from users order by id desc;

4. ORDER BY 子句 – 多重排序

对 users 表中的数据,先按照 status 字段进行降序排序,再按照username 的字母顺序,进行升序排序,示例如下:

select * from users order by status desc, username asc;

COUNT(*) 函数

  1. 语法

COUNT(*) 函数用于返回查询结果的总数据条数,语法格式如下:

  1. COUNT(*) 示例

查询 users 表中 status 为 0 的总数据条数:

select count(*) from users where status = 0

3.使用 AS 为列设置别名

如果希望给查询出来的列名称设置别名,可以使用AS 关键字,示例如下:

select count(*) as total from users where status = 0

数据库操作

1.安装 mysql 模块

mysql 模块是托管于npm 上的第三方模块。它提供了在Node.js 项目中连接和操作MySQL 数据库的能力。 想要在项目中使用它,需要先运行如下命令,将mysql 安装为项目的依赖包:

npm install mysql

2. 配置 mysql 模块

在使用 mysql 模块操作 MySQL 数据库之前,必须先对 mysql模块进行必要的配置,主要的配置步骤如下:

// 1. 导入 mysql 模块
const mysql = require('mysql')
// 2. 建立与 MySQL 数据库的连接关系
const db = mysql.createPool({
  host: '127.0.0.1', // 数据库的 IP 地址
  user: 'root', // 登录数据库的账号
  password: 'admin123', // 登录数据库的密码
  database: 'my_db_01', // 指定要操作哪个数据库
})

3. 测试 mysql 模块能否正常工作

调用 db.query() 函数,指定要执行的 SQL 语句,通过回调函数拿到执行的结果:

// 测试 mysql 模块能否正常工作
db.query('select 1', (err, results) => {
  // mysql 模块工作期间报错了
  if(err) return console.log(err.message)
  // 能够成功的执行 SQL 语句
  console.log(results)
})
const mysql = require('mysql');
const db = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: 'root',
  database: 'my_db_1',
});
//查询数据
// const sqlstr = 'select * from users';
// db.query(sqlstr, (err, result) => {
//   if (err) return console.log(err.message);
//   console.log(result);
// });
//检查连接是否成功
// db.query('SELECT 1', (err, result) => {
//   if (err) return console.log(err.message);
//   console.log(result);
// });

//插入数据--简写形式
// const user = {
//   username: '李四',
//   password: 'XX6666',
// };
// const sqlstr = 'insert into users set ?';
// //user最终拼接到上面的 ? 里面.
// db.query(sqlstr, user, (err, results) => {
//   if (err) return console.log(err.message);
//   // 根据变化的数据条数判断是否成功
//   if (results.affectedRows === 1) {
//     console.log('插入数据完毕');
//   }
// });
//查询数据
/* const sqlstr1 = 'select * from users';
db.query(sqlstr1, (err, result) => {
  if (err) return console.log(err.message);
  console.log(result);
}); */
//更新数据,就是根据id修改数据的值
// const userc = {
//   id: 6,
//   username: '张三',
//   password: 'oldtie666',
// };
// const sqlstr2 = 'update users set ? where id=?';
// db.query(sqlstr2, [userc, userc.id], (err, result) => {
//   if (err) return console.log(err.message);
//   if (result.affectedRows === 1) {
//     console.log('数据更新成功!!!');
//   }
// });
//更新数据,就是根据id修改数据的值
// const userc = {
//   id: 8,
//   username: '王二',
//   password: 'oldtie222',
// };
// const sqlstr2 = 'update users set ? where id=?';
// db.query(sqlstr2, [userc, userc.id], (err, result) => {
//   if (err) return console.log(err.message);
//   if (result.affectedRows === 1) {
//     console.log('数据更新成功!!!');
//   }
// });
//删除数据--根据id删除,id有唯一性,因为不可逆,一般不用
// const sqlstr = 'delete from users where id=?';
// db.query(sqlstr, 9, (err, result) => {
//   if (err) return console.log(err.message);
//   if (result.affectedRows === 1) {
//     console.log('删除成功了,id为9的数据永久不见了,不可逆');
//   }
// });
//标记删除--- status 改变字段数值-标记为删除
//where是限定条件,我们只标记删除id为10的数据,
const sqlstr3 = 'update users set status=? where id=?';
db.query(sqlstr3, [1, 10], (err, result) => {
  if (err) return console.log(err.message);
  if (result.affectedRows === 1) {
    console.log('标记删除成功啦,状态改为  1  ');
  }
});

分页

SELECT art.Id,art.title,art.pub_date,art.state,cate.name FROM ev_articles art LEFT JOIN ev_article_cate cate ON art.cate_id = cate.Id LIMIT 2,2