概述
什么是Node.js
Node.js是基于Chrome V8引擎的JavaScript运行环境。
终端
终端是专门为开发人员设计的,用于实现人机交互的一种方式。
终端中的快捷键
- ↑ 小方键盘上 ,可以执行上一次的命令 键盘
- tab 快速补全路径 键盘
- esc 清空输入的内容 键盘
- cla cla清空终端中的内容 字符串
Fs文件系统模块
fs模块是Node.js官方提供的,用来操作文件的模板,它提供了一系列的方法和属性,用来满足用户的操作需求
例如:
- fs.readFile()读取指定文件的内容
- fs.writeFile()写入指定文件的内容
如何导入Fs模块
const fs = require(‘fs’)
代码写在最顶部
fs.readFile(path[options],callback)
// 导入fs模块
const fs = require('fs')
// 使用fs.readFile 方法读取文件
// 参数1 ,文件的路径
// 餐数2,编码格式,一般采用utf8
// 参数3,回调函数
fs.readFile('./12.txt','utf8',function(err,dataStr){
// 失败 如果成功 err =null
// 如果失败 dataStr = undefined
console.log(err);
// 成功
console.log(dataStr);
})
fs.writeFile(file,data[options],callback)
const fs = require('fs')
// 参数1 文件路径
// 餐数2 ,传入内容
// 参数3 , 编码格式
// 参数4 ,回调函数
fs.writeFile('./12.txt','Hello','utf8',function(err) {
if (err!==null){
console.log('失败')
}
console.log('成功')
})
fs模块——路径动态拼接
如果使用相对路径./ …/开头的话,可能会导致,文件读取失败,Node是通过拼接字符串的形式来获取路径的
解决方案:
使用相对路径,对需要用node运行的文件右键复制路径,然后通过粘贴进行写入路径,但是在CSS中/表示转义的意思,所以我们需要用//表示
缺点:移植性差,不利于维护
完美解决方案
__dirname :
表示当前文件所处的目录,利用字符串拼接的形式,来提供路径
const fs = require('fs');
fs.readFile(__dirname + '/成绩单.txt','utf8',function(err,dataStr){
if(err!=null){
console.log('失败'+err.message);
}else{
console.log('成功'+dataStr)
}
console.log(__dirname);
})
path路径模块
导入path模块
const path = require(‘path’);
路径拼接
path.join()语法格式;
path join([…paths])
注意
路径拼接传进去的参数,如果有“…/”会抵消上一层路径
const fs = require('fs');
const path = require('path');
fs.readFile(path.join(__dirname, '/12.txt'),'utf8',function(err,dataStr) {
if (err){
console.log(err.message);
}
console.log(dataStr);
})
获取路径中的文件名
path.basename(path[,ext]);
第一个参数是 文件的路径
第二个参数是 文件的后缀名,如果选择,后缀名将不会打印
const path = require('path');
const lj = '/files/12.txt'
var houzhui = path.basename(lj);
console.log(houzhui);
var houzhui2 = path.basename(lj,'.txt')
console.log(houzhui2);
获得路径中文件的扩展名
path.extname(path);
就一个参数,文件的路径
const path =require('path');
const lj = './12.txt'
const kuozhanming = path.extname(lj)
console.log(kuozhanming);
http模块
http模块是Node.js官方提供的,用来创建web服务器的模块,我们可以用http.createServer()方法,就能把一台普通的电脑,变成一台Web服务器。
导入http模块
const http = require('http')
创建Web服务器
创建Web服务实例:
使用http.createServer();方法
绑定request事件,监听需求
启动服务器
使用listen()方法,如果使用80接口,地址后面可以不加入80
// 导入http模板
const http = require('http')
// 创建Web服务器实例
const server = http.createServer();
// 绑定request事件,监听客户端的需求
server.on('request',function(req,res){
console.log('欢迎')
})
// 启动服务器
server.listen(8080,function(){
console.log('启动成功 at http://127.0.0.1:8080');
})
req请求对象
req请求对象,包含两个参数
req.url 是客服端请求的URL地址
req.method 是客服端的请求类型
// 导入http模板
const http = require('http');
// 创建Web服务器
const server = http.createServer();
// 绑定监听事件
server.on('request',function(req){
const url = req.url;
const method = req.method;
console.log('你的URL地址是'+url,'你的请求类型是'+method)
})
// 启动服务器
server.listen(80,function(){
console.log('成功启动地址是 http://127.0.0.1')
})
res参数的使用
利用setHeader 解决中文乱码问题
end向客服端返回一些消息
// 解决中文乱码的问题
res.setHeader('Content-Type', 'text/html;charset=utf-8')
// res.end()向客户端响应一些消息
res.end('你是狗');
动态响应
通过req.url获得用户访问的URL地址,判断URL地址,提示不同的内容
const http = require('http');
// 创建服务器
const server = http.createServer();
// 绑定 request事件
server.on('request',function(req,res){
const url = req.url;
let content = '<h1>404 Not found!</h1>';
if(url==='/'||url==='/index.html'){
content ='<h1>首页</h1>';
}else if(url==='/about.html'){
content = '<h1>关于</h1>';
}
res.setHeader('Content-Type','text/html;charset=utf-8');
res.end(content);
})
// 启动服务器
server.listen(80,function(){
console.log('启动成功 at http://127.0.0.1')
})
模块化
模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对整个系统来说,模块是可组合,分解和更换的单元。
使用模块化的好处:
- 提高了代码的复用性
- 提高了代码的可维护性
- 可以实现按需加载
模块化的规范
模块化规范就是对代码进行模块化的拆分和组合,需要遵守的规则
Node.js中模块的分类
- 内置模块(node官方提供的)
- 自定义模块 (自己创建的)
- 第三方模块(第三方下载的)
模块作用域
在自定义模块中定义的变量,方法,只能在当前模块被访问,这种级别的访问限制,叫做模块作用域
模块作用于的好处:
防止全局变量污染
向外共享模块作用域中的成员
module对象
在每个JS的自定义模块中都有一个module对象,它里面存储了和当前模块相关的信息
module.exports对象
在自定义模块中,可以使用module.exports对象,将模块内的成员共享出去,供外界使用
// 利用exports对象传递变量和方法
module.exports ={
uname:'zs',
sayHello:function(){
console.log('Hello');
}
}
包
什么是包?
包就是第三方模块
npm包
通过 npm i 包名,进行安装
安装以后去npmjs.com 搜索包名,查看文档
快速创建package.join
使用命令 npm init -y
快速安装所有包
npm i
快速卸载包
注意:卸载包没有缩写
nup uninstall
将包安装在devDependencies节点中
如果某些包只在开发阶段用得到,建议安装在devDependencies节点中;
某些包 在开发和项目上线后都用得到,建议安装在dependencies节点中
npm i 包名 -D
包的分类
项目包:
被安装在mode_module目录中的包,叫做项目包
项目包又分为:
开发依赖包 : 存储在devDependencies里面的包 npm i 包名 -D
核心依赖包: 存储在dependencies里面的包 npm i 包名
全局包
提供-g参数
npm i 包名 -g 全局安装包
模块的加载机制
模块在第一次加载后会被缓存。这就是意味着多次调用require()不会被多次执行
注意:
不论是内置模块,用户自定义模块,还是第三方模块,都会优先从缓存中加载,从而提高模块的加载效率
内置模块的加载机制
最高优秀级。如果第三方模块,自定义模块有相同的文件名,会优先加载内置模块
自定义模块的加载机制
先加载指定的文件;
如果找不到,补全.js进行寻找
如果找不到,补全json进行寻找
如果找不到,补全node进行查找
第三方模块的加载机制
会一直往上翻,直到找到为之。
如果一直找不到,就会报错
Express
Express是基于Node.js平台,快速,开放,极简的Web开发框架
Express的本质:第三方的包,提供了快速创建Web服务器的便捷方法
Express的安装
执行命令:
npm i express@4.17.1
快速创建一个Express服务器
先导入模块,在创建服务器,然后调用linsten方法启动服务器
// 导入 express 的模块
const express = require('express');
// 创建Web服务器
const app = express();
// 调用app.listen启动服务器
app.listen(80,()=>{
console.log('express server running at http://127.0.0.1')
})
监听get请求
发送固定的数值
app.get('/user',(req, res) => {
res.send({
name:"Zs",
age:20,
sex:"男"
})
// req.query获得客服端发送的参数
// query是一个空对象
console.log(req.query)
})
发送客户端传递的数值
app.get('/',(req, res) => {
// req.query获得客服端发送的参数
// query是一个空对象
let a = {
name:req.query.name,
age:req.query.age,
}
res.send(a)
})
监听POST请求
app.post('/user',(req, res) => {
res.send('请求成功')
})
get请求动态获取参数
req .params
// get请求动态的获取参数
// res.params
app.get('/abc/:id',(req, res) => {
res.send(req.params)
})
托管静态资源
express提供了一个非常好用的函数,叫做express.static()通过它,我们可以非常方便的创建一个静态资源服务器。
// 导入express模块
const express = require('express');
// 创建服务器
const app = express();
// 利用express.static将一个文件设置静态托管,使外界可以访问
app.use(express.static('./sbx'))
app.use(express.static('./sz'))
// 如果想托管多个,只需要重复调用express.static这个函数即可
// app.use(express.static('./sbx'))
// 注意:
// 托管多个静态页面时,会根据写入的顺序去查找文件,如果有同名文件,会先调用导入前面的文件夹中的文件
// 启动服务器
app.listen('80',()=>{
console.log('http://127.0.0.1:80')
})
特别注意:
托管多个文件夹时,同名文件的调用顺序
挂载路径前缀
拼接字符串的形式
app.use('./sbx',express.static('./sbx'))
路由
按键与服务之间的映射关系
Express中的路由
客户端之间的请求与服务器处理函数之间的映射关系
由三部分组成:
请求的类型
请求的URL地址
处理函数
路由的匹配过程
每一个请求到达服务器后,经路由的匹配,匹配成功后,才会调用相关的函数。
模块化路由
创建一个JS文件,存放路由
通过express.Router()创建一个路由
给路由添加get或者POST 响应
将路由对象通过module.exports进行公共化
// 这是路由模块
// 1. 导入 express
const express = require('express')
// 2. 创建路由对象
const router = express.Router()
// 3. 挂载具体的路由
router.get('/user/list', (req, res) => {
res.send('你是猪')
})
router.post('/user/add', (req, res) => {
res.send('Add new user.')
})
// 4. 向外导出路由对象
module.exports = router
在主文件中导入
通过app.use进行导入,要先把自定义模块导入其中
const express = require('express')
const app = express()
// app.use('/files', express.static('./files'))
// 1. 导入路由模块
const router = require('./d1')
// 2. 注册路由模块
app.use(router)
// 注意: app.use() 函数的作用,就是来注册全局中间件
app.listen(80, () => {
console.log('http://127.0.0.1')
})
Express中间件
业务流程中的处理环节
对请求进行预处理
中间件必须包含next参数,去指向下一个中间件或者路由
全局中间件
使用app.use()调用的中间件函数,称为全局中间件
const express = require('express')
const app = express()
// 定义第一个全局中间件
app.use((req, res, next) => {
console.log('调用了第1个全局中间件')
next()
})
// 定义第二个全局中间件
app.use((req, res, next) => {
console.log('调用了第2个全局中间件')
next()
})
// 定义一个路由
app.get('/user', (req, res) => {
res.send('User page.')
})
app.listen(80, () => {
console.log('http://127.0.0.1')
})
// 使用app.use导入的中间件函数,叫做全局中间件,全局中间件函数必须包含next 指向下一个中间件,
// 执行顺序,即书写的顺序
局部中间件
不使用app.use()调用的中间件,通过参数,或者数组的方式在路由中进行调用的中间件称为局部中间件
// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()
// 1. 定义中间件函数
const mw1 = (req, res, next) => {
console.log('调用了局部生效的中间件')
next()
}
const mw2 = (req, res, next) => {
console.log('调用了局部生效的中间件2')
next()
}
// 2. 创建路由
app.get('/', mw1,mw2, (req, res) => {
res.send('Home page.')
})
app.get('/user', (req, res) => {
res.send('User page.')
})
// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(80, function () {
console.log('Express server running at http://127.0.0.1')
})
// 不使用 app.use调用的中间件。成为局部中间件
中间的注意事项
- 必须在路由前注册中间件,如果在路由之后注册中间件,中间件不能正常的使用
- 客户端发送过来的请求,可以连续调用多个中间件
- 必须包含next参数,调用next()方法去指向下一个中间件或者路由
- 调用next()方法后,不建议写任何代码
- 连续调用多个中间件,多个中间件共享req和res对象
中间件的分类
应用级别的中间件
- 通过app.get(),app.post(),app.use()绑定到app实例上的中间件
路由级别的中间件
- 绑定到router实例上的中间件
- 绑定到express.Router()实例上的中间件
错误级别的中间件
- 错误级别中间件的作用:专门用来捕获整个项目发生的异常错误,从而防止项目异常崩溃的问题
- 错误级别中间件具有4个参数(err,req,res,next)
- 错误级别的中间件必须在路由之后
const express = require('express');
const app = express();
app.get('/',(req,res)=>{
throw new Error('服务器发生错误')
res.send('Hello World')
})
// 错误中间件
app.use(function(err,req, res,next){
console.log('发生错误'+err.message);
res.send('发生错误'+err.message);
})
app.listen(80,function(){
console.log('http://127.0.0.1:80');
})
Express 内置的中间件
express.json()的使用
const express = require('express');
const app = express();
// 利用内置中间件解析JSON数据
// 必须在配置路由之前
app.use(express.json());
// POST请求 获取数据
app.post('/',(req,res) => {
console.log(req.body)
res.send('收到数据')
})
app.listen(80,function(){
console.log('http://127.0.0.1:80');
})
express.urlencoded()内置中间件
const express = require('express');
const app = express();
// 导入express.urlencoded内置中间件
app.use(express.urlencoded());
// POST请求
app.post('/',(req, res) => {
console.log(req.body);
res.send('收到')
})
app.listen(80,function(){
console.log('http://127.0.0.1:80');
})
第三方中间件
Express写接口
主文件
const express = require('express');
// 创建服务器
const app = express();
// 导入自定义的api模块
const routes = require('./aprRouter')
// 解析表单数据
app.use(express.urlencoded({ extended: false }))
// 注册路由
app.use('/api', routes);
// 启动服务器
app.listen(80,function(){
console.log('http://127.0.0.1:80')
})
API路由接口文件
const express = require('express')
const routes = express.Router();
// get请求
routes.get('/get',(req,res) => {
// 拿到客户端发送的数据
const query = req.query;
// 响应客户端消息
res.send({
status:0,
msg: 'GET请求成功',
data:query
})
})
// post请求
routes.post('/post',(req,res) => {
// 拿到客户端发送的数据
// 接受的数据格式为urlencoded 需要解析
const body = req.body;
// 响应客户端
res.send({
status:0,
msg: 'POST',
data:body
})
})
// 向外展示
module.exports =routes;
接口的跨域问题
CORS (主流解决方案)
JSONP (只支持get请求)
CORS
cors是Express的一个第三方中间件。
下载CORS :npm i cors
// 导入cors 模块
const cors = require('cors')
// 解決跨域问题
app.use(cors());
CORS响应头部 Access-Control-Allow-Origin
语法:
Access-Control-Allow-Origin:<origin>|*
origin参数指定了允许访问该资源的外域URL
例:
下面的代码只能是http://itcast.cn进行访问,其他访问是不返回数据的
res.setHeader('Access-Control-Allow-Origin','http://itcast.cn')
CORS请求的分类
简单请求
- GET
- POST
- HEAD
- 无定义头部字段
预检请求
- Method
- 包含自定义头部字段
- application/json格式的数据
两者区别
简单请求的特点:客服端和服务器只会发生一次请求
预检请求的特点:客户端和服务器会发生两次请求,预检请求后再发起简单请求
JSONP
浏览器通过《script》”标签的src属性,请求服务器上的数据,同时,服务器返回一个函数的调用。这种请求方式叫做JSONP
特点:
JSONP不属于ajax请求,没有XMLHttpRequest对象
JSONP只支持get请求
数据库
组织 存储 管理数据的仓库
传统型数据库的数据组织结构
在传统型数据库中,数据的组织结构分为数据库,数据表,数据行,字段这4大部分组成
在项目中使用MySQL
先执行安装命令 npm i mysql
// 导入mysql模块
const mysql = require('mysql');
// 建立与mysql数据库的联系
const db = mysql.createPool({
host:"127.0.0.1", //数据库的地址
user:'xxxxx', //账号
password:'xxxxx', // 密码
database:'ceshi1' //操作数据库的名称
})
插入数据
简便的插入数据
const sj = {username:'hh',password:'123456'}
const cryj = 'INSERT INTO users1 SET ?'
db.query(cryj,sj,(err, result) => {
if (err) return console.log(err.message)
// if(result.affectedRows===1){
// console.log('插入成功')
// }
console.log(result)
})
更新数据
const sj = {id:6,username:'xx',password:'456'}
const gxyj = 'UPDATE users1 SET ? WHERE id=6'
// 调用函数
db.query(gxyj,sj,(err, result) => {
if (err) return console.log(err.message);
if(result.affectedRows===1){
console.log('更新成功')
}
})
删除数据
const scsj = 'DELETE FROM users1 WHERE id=6';
// 调用函数
db.query(scsj,(err, result) => {
if (err) return console.log(err.message);
if(result.affectedRows===1){
console.log('删除成功')
}
})
注意
如果使用result 判断数据是否成功的更新,删除。result是一个对象,所以我们可以根据result.affectedRows方法进行判断
Web开发模式
基于服务器渲染的传统Web开发模式
- 服务器发送给客户端的HTML页面,是在服务器通过字符串的拼接,动态生成的。因此,客户端不需要使用ajax这样的技术额外请求页面
优点:
- 前端耗时少。
- 有利于SEO
缺点:
- 占用服务器端资源
- 不利于前后端分离,开发效率低
基于前后端分离的新型Web开发模式
依赖于Ajax技术的广泛应用。前后端分离的Web开发模式,就是后端负责提供API接口,前端使用Ajax调试接口的开发模式
优点:
- 开发体验好
- 用户体验好
- 减轻服务器端的渲染压力
缺点:
- 不利于SEO
身份认证
通过一定的手段,完成对用户身份的确认
服务器渲染的身份认证方式-Session认证机制
HTTP协议的无状态性
HTTP协议的无状态性,指的是客户端的每次HTTP请求都是独立的,连续多个请求之间没有直接的关系,服务器不会主动保留每次HTTP请求的状态
Cookie
Cookie是储存在用户浏览器中的一段不超过4KB的字符串。它由一个名称,一个值和其他几个用来控制Cookie有效期,安全性,使用范围的可选属性组成
触发逻辑:
当客户端发起请求时,会把所有没过期的Cokkie一同发送给服务器。
特性
自动发送
域名独立
过期时限
4KB限制
不安全性
Cookie不具有安全性
由于Cookie是存储在浏览器中的,而且浏览器也提供了读写Cookie的API,因此Cookie很容易被伪造,不具有安全性。因此不建议服务器将用户的隐私数据,通过Cookie的形式发送给浏览器
Session的工作原理
express-session中间件
JWT
可以跨域请求
跨域认证解决方案
JWT的组成部分
JWT通常由三部分组成,分别是Header(头部),Payload(有效荷载),Signature(签名),
Header.Payload.Signature
JWT的相关包的安装
npm i jsonwebtoken express-jwt
jsonwebtoken 用来生成token 转化成JWT字符串
express-jwt JWT解析成JSON对象
Secret密钥
保证JWT字符串的安全性,防止JWT字符串在网络传输中被破解
JWT实例
const express = require('express')
const app = express();
// 导入JWT相关包
const token = require('jsonwebtoken')
const jwt = require('express-jwt')
// 跨域
const cors = require('cors')
app.use(cors())
// 获得页面发送过来的数据
app.use(express.urlencoded({extended: false}))
// 定义secret 密钥 字符串随便写,越复杂越好
const secret ='mynameyisizhaoyipeng no1 0.0'
// 注册将JWT字符串解析还原成JSON对象的中间件
// unless可以配置不需要接口权限的地址
// 更新以后的jWT 需要加入algorithms:['HS256'],设置JWT的算法
app.use(jwt({secret:secret,algorithms:['HS256']}).unless({path:[/^/api//]}))
// 全局中间件,铺货JSW失败的原因
app.use((err, req, res, next) => {
// 这次错误是由 token 解析失败导致的
if (err.name === 'UnauthorizedError') {
return res.send({
status: 401,
message: '无效的token',
})
}
res.send({
status: 500,
message: '未知的错误',
})
})
// post请求
app.post('/api/login',(req, res) => {
// 将req.body请求体中的数据,转存为userinfo常量
const userinfo = req.body
if (userinfo.username !== 'admin' || userinfo.password !== '000000') {
return res.send({
status: 400,
message: '登录失败!',
})
}
// 利用jsonwebtoken 生成token
const tokenStr = token.sign({username:userinfo.username},secret,{expiresIn:'1s'})
res.send({
status:0,
meg:"账号密码正确,允许登录",
token:tokenStr,
})
})
// 有权限的接口
app.get('/admin/getinfo',(req, res)=>{
console.log(req.user)
res.send({
status:0,
msg:'获取token成功',
data:req.use
})
})
// 启动服务器
app.listen(8888,function(){
console.log('http://127.0.0.1:8888')
})
最后
以上就是风中黄蜂为你收集整理的node学习总结的全部内容,希望文章能够帮你解决node学习总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复