Node.js
1.入门
1.下载
2.初识 Node.js
Nodejs@ is a JavaScript runtime built on Chrome’s V8 JavaScript engine.
Node.js 是一个基于Chrome V8引擎的JavaScript 运行环境。
Node.js 的官网地址:https://nodejs.org/zh-cn/
3.fs 文件系统模块
1.什么是fs 文件系统模块
fs 模块是Node.js官方提供的、用来操作文件的模块。它提供了一系列的方法和属性,用来满足用户对文件的操作需求。
例如:
fs.readFile()方法,用来读取指定文件中的内容
fs.writefile()方法,用来向指定的文件中写入内容
如果要在JavaScript代码中,使用fs模块来操作文件,则需要使用如下的方式先导入它:
const fs = require(‘fs’)
2.fs 文件系统模块
1.读取指定文件中的内容
fs.readFile()的语法格式
使用 fs.readFile()方法,可以读取指定文件中的内容,语法格式如下:
1 fs.readFile(path,[options], callback)
参数1:必选参数,字符串,表示文件的路径
参数2:可选参数,表示以什么编码格式来读取文件
参数3:必选参数,文件读取完成后,通过回调函数拿到读取的结果
2.向指定的文件中写入内容
1.fs.writeFile()的语法格式
使用 fs.writeFile0方法,可以向指定的文件中写入内容,语法格式如下:
1 fs.writeFile(file, data,[options], callback)
参数1:必选参数,需要指定一个文件路径的字符串,表示文件的存放路径
参数2:必选参数,表示要写入的内容
参数3:可选参数,表示以什么格式写入文件内容,默认值是 utf8
const fs=require('fs');
/* fs.readFile("1.txt","utf-8",function(err,dataStr)
{
console.log(dataStr);
}) */
/* fs.writeFile("1.txt","ik","utf-8",function(err){
console.log(err);
}) */
fs.readFile("1.txt","utf-8",function(err,dataStr)
{
const arrNew=[];
const arr = dataStr.split(' ');
arr.forEach(item=>{
arrNew.push(item.replace('=',':'));
})
const garr=arrNew.join('\r\n');
console.log(arr);
console.log(arrNew);
console.log(garr);
fs.writeFile('2.txt',garr,'utf-8',function(err){
console.log(err);
})
})
2.路径
1.路径的拼接
路径的拼接使用join方法
const path = require("path");
const pathStr = path.join('/a','/b/c','../../','./d','e');
console.log(pathStr);
__dirname 路径名
2.获取路径中的文件名
basename
path1="1.txt";
const str = path.basename(path1,".txt");
console.log(str);
3.获取文件的后缀名
extname
const fpath= "1.txt";
const ftxt = path.extname(fpath);
console.log(ftxt);
小脚本
const fs =require("fs");
const path = require("path");
const regStyle = /<style>[\s\S]*<\/style>/
const regScript = /<script>[\s\S]*<\/script>/
fs.readFile("./index.html",'utf-8',function(err,dataStr){
if (err) return console.log("读取失败"+err.message);
resolveCSS(dataStr);
resolveScript(dataStr);
resolveHTML(dataStr);
})
function resolveCSS(htmlstr){
const str1 = regStyle.exec(htmlstr);
const nstr = str1[0].replace('<style>','').replace('</style>','');
fs.writeFile(path.join(__dirname,'/clcok.css'),nstr,function(err,dataStr){
if (err) return console.log("写入失败");
console.log("写入成功");
})
}
function resolveScript(htmlstr1){
const str2 = regScript.exec(htmlstr1);
const nstr2 = str2[0].replace('<script>','').replace('</script>','');
fs.writeFile(path.join(__dirname,'/clcoks.js'),nstr2,function(err,dataStr){
if (err) return console.log("写入失败");
console.log("写入成功");
})
}
function resolveHTML(htmlstr){
const html = htmlstr.replace(regStyle,'<link rel="stylesheet" href="./clcok.css">').replace(regScript,'<script src="./clcoks.js"></script>');
fs.writeFile('index.html',html,function(err,dataStr){
if (err) return console.log("写入失败");
console.log("写入成功");
})
}
后写入的内容会覆盖之前写入的内容
3.http模块
1.导入http模块
const http = require(‘http’)
const http = require('http')
const serve = http.createServer()
serve.on('request',(req,res)=>{
console.log("web serve start");
})
serve.listen(1910,()=>{
console.log("port:"+1910);
})
req.url 获取网址
req.method 获取请求方式
serve.on('request',function(req,res){
const url = req.url;
const method = req.method;
console.log(url+" "+method);
})
解决中文乱码
res.setHeader(‘Content-Type’,‘text/html; charset=utf-8’);
const http = require('http');
const serve =http.createServer();
serve.on('request',function(req,res){
const url = req.url;
const method = req.method;
console.log(url+" "+method);
const str = "启动";
res.setHeader('Content-Type','text/html; charset=utf-8');
res.end(str);
})
serve.listen(1910,function(){
console.log("启动");
})
const http = require('http');
const serve = http.createServer();
serve.on('request',function(req,res){
const url = req.url;
let content = '404 Not Found';
if (url === '/' || url === '/index.html'){
content = '<h1>首页</h1>'
}else if (url === '/other.html'){
content = '<h2>其他</h2>'
}
res.setHeader('Content-Type','text/html; charset=utf-8');
res.end(content);
})
serve.listen(1910,function(){
console.log("启动服务");
})
5.小案例
const fs = require("fs");
const http = require("http");
const path = require("path");
const serve = http.createServer();
serve.on('request',(req,res)=>{
const url = req.url;
const str1 = path.join(__dirname,url);
console.log(str1);
fs.readFile(str1,'utf-8',function(err,dataStr){
if (err) return res.end("404 Not found");
res.end(dataStr);
})
})
serve.listen(1910,function(){
console.log("启动");
})
4.模块化
1.模块的规范性
模块化规范就是对代码进行模块化的拆分与组合时,需要遵守的那些规则。
例如:
使用什么样的语法格式来引用模块
在模块中使用什么样的语法格式向外暴露成员
模块化规范的好处:大家都遵守同样的模块化规范写代码,降低了沟通的成本,极大方便了各个模块之间的相互调用利人利己
2.Node.js模块
- 内置模块 fs path http
- 自定义模块 .js 用户创建
- 第三方模块 第三方开发的模块
加载模块
require()
3.模块作用域
在自定义模块中的变量、方法等成员,只能在当前模块内被访问,这种模块级别的限制就叫做模块作用域
好处
- 防止全局变量被污染
向外共享模块作用域中的成员
moudule对象
存储和当前模块有关的信息
moudule.exports对象
可以将模块的成员共享出去,供外界使用
在外界用require()导入自定义模块得到moudule.exports对象
默认情况下moudule.exports等于空对象
module.exports.uname = "zs";
module.exports.say = function(){
console.log("Hi");
}
以moudule.exports指向的对象为准
module.exports.uname = "zs";
module.exports.say = function(){
console.log("Hi");
}
module.exports = {
nuname : 'ls',
nsay(){
console.log("HHi")
}
}
exports对象
moudule.exports对象与exports对象指向同一个对象
exports.uname='ls';
exports.age=19;
建议不要在同一个文件使用moudule.export、exports
4.CommonJS规范
1.每个模块的moudule代表当前模块
2.moudule变量是一个对象,moudule.export是一个接口
3.require()用来加载模块
5.npm包
1.格式化时间
function dateformat(dastr){
function zero(str){
if (str<10) return '0'+str
}
const dt = new Date(dastr);
const m = dt.getFullYear();
const n = zero(dt.getMonth());
const d = zero(dt.getDay());
return `${m}-${n}-${d}`;
}
module.exports.dateformat=dateformat;
const req = require("./time")
const dt = new Date();
const s = req.dateformat(dt);
console.log(s)
2.
npm install 包名
简写
npm i 包名
const moment = require("moment");
const dt = moment().format('YYYY-MM-DD');
console.log(dt);
npm i moment@版本 安装指定版本的包
3.包的语义化版本规范
2.24.0
- 1->大版本
- 2->功能版本
- 3->Bug修复版本
4.包管理配置文件
快速创建package.json文件
npm init -y
要在gitingnore文件添加node_modules
5.dependencies
用来记录使用npm下载了哪些包
npm i 直接安装所有包
npm uninstall 包名 卸载包
6.devDependencies
某些包只在开发阶段使用,加入devDependencies节点
某些包在开发使用上线也需要使用,加入dependencies节点
npm install webpack -D
7.镜像源
查看当前镜像源
npm config get registry
npm config set registry=https://registry.npm.taobao.org/
nrm
方便地切换镜像源
npx nrm ls
npx nrm use taobao
8.包的分类
项目包,被安装到node_moudules目录
- 开发依赖包 devDependencies
- 核心依赖包 dependencies
全局包,在使用npm install 加上-g参数
C:\Users\用户名\AppData\Roaming\npm\node_modules
npm uninstall 包名 -g
i5ting_toc
可以把md转成html
npm install -g i5ting_toc
i5ting_toc -f .md -o
9.包的规范
1.单独目录存在
2.有文件package.json
3.有name,version,main三个属性,包名,版本号,包的入口
10.自定义包
新建文件夹作为根目录
1.package.json
2.index.js
3.README.md
function htmlEscape(htmlstr){
return htmlstr.replace(/<|>|"|&/g,match=>{
switch (match){
case '<':
return '<';
case '>':
return '>'
case '"':
return '"'
case '&':
return '&'
}
})
}
function htmlUnEscape(htmlstr){
return htmlstr.replace(/<|>|"|&/g,match=>{
switch (match){
case '<':
return '<';
case '>':
return '>'
case '"':
return '"'
case '&':
return '&'
}
})
}
module.exports={
htmlEscape,
htmlUnEscape
}
模块拆分
src
const html = require("./src/html")
const unhtml = require("./src/unhtml")
module.exports={
...html,
...unhtml
}
11.发布npm包
1.注册npm账号
2.登录 npm login
3.npm publish 发布
4.删除包 npm unpublish 包名 --force
只能删除72小时以内发布的包
删除的包,在24小时内不允许发布没有意义的包
12.模块的加载机制
模块加载一次后会被缓存
内置模块加载优先级最高
在载入内置模块是要以./或…/开头
默认加载main入口,如果没找到,会找index.js否则报错
6.Express
1.基本使用
获取url中携带的参数
req.query
2.获取url中的动态参数
const express = require("express");
const app = express();
app.all("/serve/:id",function(req,res){
console.log(req.params);
const str = JSON.stringify(req.params)
res.end(str)
})
app.listen(4400,()=>{
console.log("启动服务");
})
3.托管静态资源
express.static0)
创建一个静态资源服务器,通过如下代码就可以将public目录下的图片、CSS文件、JavaScript 文件对外开放访问了:
app.use(express.static(‘public’))
app.use(‘/file’,express.static(‘public’))
http://localhost:3000/images/bg.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/login.js
注意:Express 在指定的静态目录中查找文件,并对外提供资源的访问路径
因此,存放静态文件的目录名不会出现在URL中
有多个静态资源目录就多次调用这个函数
4.路由模块
const express = require("express");
const router = express.Router();
router.get("/serve/:id",function(req,res){
console.log(req.params);
const str = JSON.stringify(req.params);
res.end(str);
})
router.post("/serve",function(req,res){
console.log("POST");
res.end("123");
})
module.exports = router;
const express = require("express");
const app = express();
const router = require('./model1')
app.use(router);
app.listen(4400,()=>{
console.log("启动服务");
})
7.中间件
1.简介
本质是一个function处理函数
必须包含next函数,路由处理函数只包含req和res
next->把流转关系交给下一个中间件和路由
const mv = function(req,res,next){
console.log("中间件函数");
next();
}
//将mv注册为全局生效的中间件
app.use(mv);
2.简写形式
app.use(function(req,res,next){
console.log("中间件");
next();
})
3.在中间件挂载属性
app.use(function(req,res,next){
console.log("中间件");
const time =new Date()
req.stime = time;
next();
})
app.all('/',(req,res)=>{
console.log(req.stime);
res.end(req.stime)
})
4.定义多个全局中间件
多次调用use方法
const express = require("express");
const app = express();
app.use(function(req,res,next){
console.log("1");
next();
})
app.use(function(req,res,next){
console.log("2");
next();
})
app.all('/',(req,res)=>{
res.end("1")
})
app.listen(4400,()=>{
console.log("启动服务");
})
5.局部生效的中间件
不适用app.use()声明
const express = require("express");
const app = express();
const mv = function(req,res,next){
console.log("局部中间件");
next();
}
app.all('/',mv,(req,res)=>{
res.send("HOME");
})
app.listen(4400,()=>{
console.log("启动服务");
})
定义多个中间件
const mv1 = function(req,res,next){
console.log("局部中间件1");
next();
}
const mv2 = function(req,res,next){
console.log("局部中间件2");
next();
}
app.all('/serve',mv1,mv2,(req,res)=>{
res.send("HOME1");
})
app.all('/serve',[mv1,mv2],(req,res)=>{
res.send("HOME1");
})
mv1,mv2 === [mv1,mv2]
6.注意事项
一定要在路由的之前定义中间件
客户端发过来的请求,可以连续调用多个中间件进行处理
执行完中间件代码后要调用next函数
next函数后面不要再写代码
连续调用多个中间件时,连续多个中间件共享req和res对象
7.中间件的分类
5大类
应用级别的中间件
绑定到了app.use,app.get,app.post,绑定到了app实例上的中间件
路由级别的中间件
绑定到express.Router
错误级别的中间件,用来捕获整个项目发生的异常错误,从而防止项目异常崩溃
(err,req,res,next)
express内置的中间件
express.static 托管静态资源
express.json 解析JSON格式的请求实体数据
express.urlencoded 解析URL-encoded格式的请求实体数据
const express = require("express");
const app = express();
app.use(function(req,res,next){
console.log("1");
next();
})
/* 配置解析json格式的数据 */
app.use(express.json)
app.use(express.urlencoded({extented:false}))
app.post('/serve',(req,res)=>{
/* req.body获取请求体的数据 */
console.log(req.body);
res.end(req.body)
})
app.listen(4400,()=>{
console.log("启动服务");
})
第三方中间件
require()
app.use()
8.自定义中间件
const express = require("express");
const app = express();
const qs = require("querystring");
/* 数据量较大无法一次传输完 */
const mymod = function(req,res,next){
/* 监听data事件 */
let str=''
req.on('data',(Chunk)=>{
str += Chunk;
})
/* 当数据接受完毕会触发end事件 */
req.on('end',()=> {
const body = qs.parse(str);
req.body=body;
next();
})
}
module.exports = mymod;
const express = require("express");
const mymod = require("./moudule");
const app = express();
app.use(mymod);
app.post('/',function(req,res){
console.log(req.body);
res.end("end");
})
app.listen(4400,()=>{
console.log("启动服务");
})
9.接口跨域问题
1.cors中间件
1.npm i cors
2.const cors = require(“cors”)
3.app.use(cors)
CORS
由一系列HTTP响应头组成
在服务端进行配置,不需要做额外配置
在浏览器中有兼容性
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors());
app.all('/',(req,res)=>{
res.send("a");
})
app.listen(4400,()=>{
console.log("启动");
})
10.前后端的身份认证
npm i jsonwebtoken
npm i express-jwt
1.导入JWT相关的包
const express = require('express');
const app = express();
const jwt = require("jsonwebtoken");
const expressjwt = require("express-jwt");
app.listen(4400,()=>{
console.log("qd");
})
2.secret密钥
const secretKey = “-hi”;
3.生成jwt字符串
jsonwebtoken的sign()方法
app.all('/',(req,res)=>{
const tokenstr=jwt.sign({username:'zs'},secret,{expiresIn:'30s'});
res.send({
status:200,
message:"dl",
token:tokenstr
})
})
4.解析还原成JSON对象
express-jwt
app.use(expressjwt({secret:secret})).unless({path:[/^\/api\//]})
//secret->密钥
//unless不需要解析的路径
const jwt = require("jsonwebtoken");
const { expressjwt:expressJWT } = require("express-jwt");
const secret = "^-^hi";
app.use(expressJWT({secret:secret, algorithms:['HS256']}));
5.捕获错误信息
定义一个全局的中间件
app.use((err,req,res,next)=>{
//if (err.name=)
})
11.node项目
1.创建项目
npm init -y
安装express
const express = require("express");
const app = express();
app.listen(4400,()=>{
console.log("启动服务器");
})
配置cors跨域
const cors = require("cors");
app.use(cors);
配置表单解析的中间件
//解析x-www格式
app.use(express.urlencoded({extended:false}));
安装mysql,创建数据库和数据库表
npm i mysql
创建db文件夹和index.js
const mysql =require("mysql");
const db = mysql.createPool({
host:'127.0.0.1',
user:'root',
password:'12345678',
database:'test'
})
module.exports=db;
注册用户相关功能的实现
const { request } = require("express");
/* 导入数据库操作模块 */
const db = require("../dp/index.js")
exports.reguser=(req,res)=>{
const mes = req.body;
if (!mes.username || !mes.password){
res.end("error");
}
const sqlstr = "select * from ev_users where username=?"
db.query(sqlstr,mes.username,(err,results)=>{
if (err){
return res.send({
status:200,
Message:err.message
})
}
if (results.length > 0){
return res.send({
status:200,
Message:"用户名被占用"
})
}else{
res.send("reg ok");
}
})
//res.send("reg ok");
}
exports.loguser=(req,res)=>{
res.send("log ok");
}
对密码进行加密
bcryptjs
npm i [email protected]
const bcrypt=require("bcryptjs");
mes.password = bcrypt.hashSync(mes.password,10);
生成jwt的Token字符串
npm i jsonwebtoken
const user = {...results[0],password:'',user_pic:''};
const tokenstr = jwt.sign(user,config.jwtSecretKey,{expiresIn: config.experiments})
res.send({
status:200,
message:"登录成功",
token:'Bearer '+tokenstr
});
解析token的中间件
npm i [email protected]
app.use(expressJWT({secret:config.jwtSecretKey}).unless({path:/^\/login/}));