天津购物网站搭建,房产网签备案是什么意思,网站 微信认证,wordpress必须关注公众号node.js学习实操及笔记 温故node.js#xff0c;node.js学习实操过程及笔记~ node.js学习视频node.js官网node.js中文网实操笔记githubcsdn笔记
为什么学node.js
可以让别人访问我们编写的网页为后续的框架学习打下基础#xff0c;三大框架vue react angular离不开node.js
…node.js学习实操及笔记 温故node.jsnode.js学习实操过程及笔记~ node.js学习视频node.js官网node.js中文网实操笔记githubcsdn笔记
为什么学node.js
可以让别人访问我们编写的网页为后续的框架学习打下基础三大框架vue react angular离不开node.js
node.js是什么
官网node.js是一个开源的、跨平台的运行JavaScript的运行环境。通俗理解: 一款应用程序一款软件可以运行JavaScript
node.js作用
开发服务器应用开发工具类应用开发桌面类应用
node.js安装
node.js官网node.js中文网全部版本安装包淘宝镜像 点击安装傻瓜式安装。 PS:推荐使用nvm方式安装node.js这样可实现自由切换版本好。 因为有的老项目node.js可能是12版本的新项目又是18或者20版本。具体安装自行查阅目前这边已经安装忘记哪个博主写的较好就不推荐了。 检测安装是否成功,输入以下命令到命令行出来版本号代表安装成功
node -v若安装失败考虑大可能为环境变量配置问题影响
node.js初体验
当前目录新建hello.js
console.log(hello node.js!);切换到当前目录终端打开执行代码看到 hello node.js 注意运行命令为node 文件路径 》hello.js是相对文件路径这里省略了./hello.js
node hello.jsnode.js注意事项
node.js不能使用BOM、DOM的API可以使用console和定时器APInode.js中顶级对象为global,也可以用globalThis访问顶级对象
// BOM不可用
console.log(window);
console.log(history);
console.log(navigator);
console.log(location)
//DOM不可用
console.log(document);
//global可用 globalthis可用
console.log(global)
//定时器可用
setTimeout((){console.log(hello~)
})Buffer缓冲器
Buffer概念
概念
Buffer是一个类似数组的对象用于固定长度的字节序列Buffer本质是一段内存空间专门用来处理二进制数据
特点
Buffer大小固定且无法调整Buffer性能较好可以直接对计算机内存进行操作每个元素的大小为1字节 3.创建BufferallocallocUnsafefrom node.js内置模块Buffer,不需引入理解为全局变量 //1.alloc
let buf Buffer.alloc(10);
console.log(buf);
console.log(-------)
// 2.allocUnsafe;
let buf_2 Buffer.allocUnsafe(10000);
console.log(buf_2);
console.log(-------)
//3.from
//打印出ASCII码字符代码表的值
let buf_3 Buffer.from(hello);
console.log(buf_3);
console.log(-------);
//打印出二进制的值
let buf_4 Buffer.from([105, 108, 111, 118, 101, 121, 111, 117]);
console.log(buf_4);
console.log(-------);Buffer操作以及注意点
字符串转换默认采用utf-8方式转换
let buf_4 Buffer.from([105, 108, 111, 118, 101, 121, 111, 117]);
console.log(buf_4);
console.log(-------);
//1-字符串转换 默认采用utf-8方式转换
const str buf_4.toString();
console.log(str);元素的读取以及修改
[]进行单个元素的读取以及修改大于255的值溢出舍弃高位留下后8位二进制utf-8编码方式1个汉字对应3个字节
let buf_5 Buffer.from(hello);
//1-[]括号方式进行单个元素的查看 二进制转换的查看
console.log(buf_5[0]);//打印出十进制
console.log(buf_5[0].toString(2));//实际上是01101000
//2-单个元素的修改
// 直接修改
buf_5[0] 95;
//查看修改后的字符串的值
console.log(buf_5.toString());//输出_ello
//溢出
buf_5[0] 361;//舍弃高位超出8位的数字 0001 0110 1001
console.log(buf_5);//69 0001被舍弃留下0110 1001
//中文
let buf_6 Buffer.from(你好);//utf-8编码方式 1个汉字对应3个中文
console.log(buf_6);//输出Buffer e4 bd a0 e5 a5 bd计算机基础
计算机基本组成
CPU 中央处理器运算与控制的核心。工作时会产生大量热量一般连接一个散热器进行散热。内存 读写速度较快断电丢失数据硬盘 读写速度较慢断电不丢失数据主板 CPU 内存 硬盘 通过主板连接在一起显卡 负责处理视频信号有信息需要在显示器呈现就会将信号传递到显卡显卡处理完毕再将信号传递给显示器显示器最终显示
程序运行基本流程
安装好上面CPU等还需安装操作系统方可运行。 操作系统 操作系统也是一种应用程序用来管理和调度硬件资源。将操作系统安装到硬盘电脑即可开机运行。 常见操作系统 WindowsLinuxMacOs 总结程序一般保存到硬盘中软件安装的过程就是将程序写入硬盘的过程。程序在运行时会加载进入内存然后由CPU读取并执行程序
进程与线程 进程包含一个或多个线程。进程线程 进程
通俗理解为进行中的程序进程是程序的一次执行过程
线程
线程是一个进程中执行的一个执行流一个线程是属于某个进程的
fs模块 全称file system 文件系统。fs模块可以实现与硬盘的交互。 例如文件的创建、删除、重命名、移动还有文件内容的写入、读取以及文件夹的操作。 写入文件
语法 fs.writeFile(file,data[,option],callback)
同步与异步 异步情况比如做饭按下了煮饭键就去炒菜。同步类似排队一个完成接着一个。对效率要求高的基本都是用异步API。 异步写入语法 fs.writeFile(file,data[,option],callback)同步写入语法 fs.writeFileSync(file,data[,option])
/** 需求* 新建一个文件夹为座右铭.txtinfo.txt)* 写入内容为 三人行必有我师焉。*/
const fs require(fs);
//写入文件 异步写入
fs.writeFile(./info.txt, 三人行必有我师焉, (err) {if (err) {console.error(写入错误)console.error(err);return;}console.log(写入成功)
})//写入文件
// 同步写入
fs.writeFileSync(./infoSync.txt, 测试同步写入);// 流式写入
const ws fs.createWriteStream(./writeStream.txt);
ws.write(床前明月光\r\n);
ws.write(疑是地上霜\r\n);
ws.write(举头望明月\r\n);
ws.write(低头思故乡\r\n);
//关闭
ws.end();
文件追加写入 文件追加多用于程序日志不断往文件追加内容 方法说明fs.appendFile(file,data[,option],callback)异步追加fs.appendFileSync(file,data[,option])同步追加fs.writeFile(file,data[,option],callback)添加标识异步追加option为{flag:a}
// 文件追加写入
const fs require(fs);
// 异步追加
fs.appendFile(./info.txt, \r\n哈哈哈追加内容下, err {if (err) {console.error(err);return;}console.log(追加内容成功)
})
//同步追加内容
fs.appendFileSync(./infoSync.txt, \r\n同步追加内容看看);
// 异步追加内容
fs.writeFile(./info.txt, \r\n哈哈哈writeFile追加, {flag: a}, err {if (err) {console.error(追加错误);console.error(err);return;}console.log(追加成功)
})
流式写入 程序打开一个文件需要消耗资源流式写入可以减少文件的次数。 流式写入方式适用于大文件写入或者频繁写入的场景writeFile适用于写入频率较低的场景。 流式读取减少连接次数连接后不断开语法fs.createWriteStream(path[,option])
参数说明
path 文件路径options选项配置
返回值 Object
代码示例
//写入文件
// 同步写入
fs.writeFileSync(./infoSync.txt, 测试同步写入);// 流式写入
const ws fs.createWriteStream(./writeStream.txt);
ws.write(床前明月光\r\n);
ws.write(疑是地上霜\r\n);
ws.write(举头望明月\r\n);
ws.write(低头思故乡\r\n);
//关闭
ws.end();文件写入应用场景
当需要持久化保存数据的时候应该想到文件写入
下载文件安装软件保存程序日志如Git编辑器保存文件视频录制
文件读取 程序从文件中取出其中的数据。 方法说明fs.readFile(file,data[,option],callback)异步读取fs.readFileSync(file,data[,option])同步读取fs.createReadStream(file,data[,option],callback)流式读取
代码示例
// 文件读取
const fs require(fs);
// 异步读取
fs.readFile(./info.txt, (err, data) {if (err) {console.error(读取错误);console.error(err);return;}console.log(读取成功)console.log(data.toString());
})
console.log(-----------------);
// 同步读取
const readDataSync fs.readFileSync(./infoSync.txt);
console.log(同步读取)
console.log(readDataSync.toString());
console.log(-----------------);
// 流式读取
// 创建视频流对象
const rs fs.createReadStream(./writeStream.txt);
// 绑定data事件 chunk 块
rs.on(data, chunk {console.log(---------!!----------);// 字符串类文件读取可以要是读取的的mp4文件用toString输出将会乱码直接console.log(chunk)即可console.log(chunk.toString());console.log(---------!!----------);
})
// end可选事件
rs.on(end, () {console.log(流式读取完成);
})
读取文件应用场景
电脑开机程序运行编辑器打开文件查看图片播放视频播放音乐Git查看日志上传文件查看聊天记录
fs练习_复制文件
代码示例
/** fs练习_复制文件* 将writeSteam.txt内容复制新建writeStreamCopy.txt*/
// 思路
// 1- readFile读取内容
// 2- writeFile新建文件
// 1、同步读取写入
const fs require(fs);
// 读取
const readDataCopy fs.readFileSync(./writeStream.txt);
// 写入
fs.writeFileSync(./writeStreamCopy.txt, readDataCopy);
console.log(测试内存);
// PS:注释下面流式读取 得出内存
console.log(process.memoryUsage());// 28119040字节 ➗1024 约等于 281366.25kb ➗1024 约等于 274.78Mb
console.log(------------------------);
// 2、流式读取写入
//创建读取流对象
const rsCopy fs.createReadStream(./writeStream.txt);
// 创建写入流对象
const wsCopy fs.createWriteStream(./writeStreamCopyStream.txt);
// 1-绑定data事件
rsCopy.on(data, chunk {wsCopy.write(chunk);
})// 2-on(data)方法复制或直接使用 管道 直接复制
// rsCopy.pipe(wsCopy);// rsCopy.on(end, () {
// console.log(测试内存);
// // PS:注释上面直接读取 得出内存
// console.log(process.memoryUsage());// 28434432字节 ➗1024 约等于 27768kb ➗1024 约等于 27.117Mb
// console.log(------------------------);
// })文件重命名和移动
异步移动语法 fs.rename(oldPath,newPath,callback)同步移动语法fs.renameSync(oldPath,newPath)
参数说明
oldPath:文件当前路径newPath:文件新的路径callback操作后的回调
代码示例
// fs重命名
const fs require(fs);//重命名将文件1重命名为infoRename.txt
fs.rename(./info.txt, ./infoRename.txt, err {if (err) {console.error(重命名失败);console.error(err);return;}console.log(重命名成功);
})// 确保目标目录存在
if (!fs.existsSync(./file)) {fs.mkdirSync(./file);
}// 移动将重命名后的文件1移动到file文件夹命名为info.txt
fs.rename(./infoSync.txt, ./file/infoMove.txt, err {if (err) {console.error(移动失败);console.error(err);return;}console.log(移动成功);
})
文件删除 异步删除语法 fs.unlink(path,callback) 同步删除语法fs.unlinkSync(path) 异步删除fs.rm(path,callback) ps:node.js14.4版本以上才可用 同步删除fs.rmSync(path) ps:node.js14.4版本以上才可用
参数说明:
path:文件路径callback操作后的回调
代码示例
// 文件删除
const fs require(fs);
//unlink删除
fs.unlink(./info.txt, (err) {if (err) {console.error(err);return;}console.log(删除成功);
})
fs.unlinkSync(./infoSync.txt);// rm删除 node.js14.4版本以上
fs.rm(./writeStream.txt, (err) {if (err) {console.error(err);return;}console.log(删除成功2);
})
fs.rmSync(./writeStreamCopyStream.txt);
文件夹操作
创建文件夹mkdir/mkdirSync读取文件夹readdir/readdirSync删除文件夹rmdir/rmdirSync
方法说明mkdir/mkdirSync创建文件夹readdir/readdirSync读取文件夹rmdir/rmdirSync删除文件夹
PS:判断文件夹是否存在
同步判断语法 fs.existsSync(path[,option])
参数说明:
path:文件路径
创建文件夹
异步创建语法fs.mkdir(path,callback)同步创建语法fs.mkdirSync(path)
代码示例
// 文件夹操作_创建文件夹
const fs require(fs);
// 创建文件
//先判断是否存在
if (!fs.existsSync(./newFile)) {fs.mkdir(./newFile, err {if (err) {console.log(创建失败);console.error(err);return;}console.log(创建成功);})
}
//先判断是否存在
if (!fs.existsSync(./a/b/c, {recursive: true})) {
// 递归创建文件夹fs.mkdir(./a/b/c, {recursive: true}, err {if (err) {console.log(创建失败2);console.error(err);return;}console.log(创建成功2);})
}
//先判断是否存在
if (!fs.existsSync(./test2/d/e, {recursive: true})) {fs.mkdirSync(./test2/d/e, {recursive: true});
}读取文件夹
异步读取语法fs.readdir(path,callback)同步读取语法fs.readdirSync(path)
参数说明
path:路径
代码示例
// 文件夹操作——读取文件夹
const fs require(fs);
// 创建文件
fs.readdir(./newFile, (err, data) {if (err) {console.log(读取文件夹失败);console.error(err);return;}console.log(读取文件夹成功);console.log(data);
})
// 读取文件夹
fs.readdir(./file, (err, data) {if (err) {console.log(读取文件夹失败2);console.error(err);return;}console.log(读取文件夹成功2);console.log(data);
})
const readfileData fs.readdirSync(./test2);
console.log(同步读取文件夹);
console.log(readfileData);删除文件夹
不推荐使用rmdir
异步删除语法fs.rmdir(path,callback)同步删除语法fs.rmdirSync(path)
推荐使用rm:
异步删除语法fs.rm(path,callback)同步删除语法fs.rmSync(path)
参数说明
path:路径
代码示例
// 删除文件夹
const fs require(fs);
//递归删除 不推荐使用rmdir 推荐使用rm
fs.rmdir(./a,{ recursive: true }, (err) {if(err){console.log(删除文件夹出错);console.error(err);return;}console.log(删除文件夹成功);
})
fs.rmdirSync(./test2, {recursive: true});//rm删除
fs.rm(./newFile,{ recursive: true }, (err) {if(err){console.log(删除文件夹出错2);console.error(err);return;}console.log(删除文件夹成功2);
})
fs.rmSync(./test, {recursive: true});
查看资源状态
异步查看语法fs.stat(path[,option],callback)同步查看语法 fs.statSync(path[,option])
参数说明
path 文件路径options 选项配置可选callback 操作后的回调
示例代码fs_stat.js
/** 查看资源状态* fs.stat()*/
const fs require(fs);
// 异步获取状态
fs.stat(./info.txt, (err, data) {if(err){console.log(查看资源失败)console.log(err);return;}console.log(异步查看资源成功详细信息如下)console.log(data);//判断是否是一个文件方法 isFile()console.log(是文件吗)console.log(data.isFile());// 判断是否是一个文件夹方法 isDirectory()console.log(是文件夹吗)console.log(data.isDirectory());
})
// 同步获取状态
const data fs.statSync(./info.txt);
console.log(同步查看资源成功详细信息如下)
console.log(data);结果值对象结构
size 文件体积birthtime 创建时间mtime 最后修改时间isFile 检测是否为文件isDirectory 检测是否为文件夹…
路径补充说明 路径分为相对路径和绝对路径两种写法 相对路径
比如在当前根目录的info.txt
相对路径表达为./info.txt
相对路径常遇到的bug与解决 相对路径参照的是命名行的工作目录 Bug:
比如在 代码利用相对路径创建文件./info.txt
在当前命令运行node fs_writeFile.js就在当前文件夹生成info.txt在nodejs上层运行node ./nodejs/fs_writeFile.js就会在nodejs同级生成info.txt
结论
相对路径的参照物 是在运行命令行的当前目录
解决方法
利用绝对路径使用全局变量__dirname进行拼接保存的是所在文件的所在目录的绝对路径
代码示例
//使用绝对路径__dirname拼接方式
//利用绝对路径使用全局变量__dirname进行拼接保存的是所在文件的所在目录的绝对路径
fs.writeFileSync(__dirname/index.html,写入内容哈哈哈哈)绝对路径 常会遇到权限的问题 比如在D盘下的info.txt
绝对路径表达为D:/info.txtlinux操作系统下用的较多/开头比如/info.txt
fs练习_批量重命名
优化如下
视频用的是split会拆分这里我用的是正则表达式视频用的是相对路径这里我拼接了__dirname使用了绝对路径
示例代码
/** 批量重命名* 需求将code文件夹里面的文件* 名称为前面为1-9的命名为01-09*/
// 思路
// 1-读取readdirSync里面的文件名称 fs.readdirSync(path,callback)
// 2-重命名renameSync fs.renameSync(path,callback)
const fs require(fs);
const files fs.readdirSync(__dirname /code);
console.log(名称为);
console.log(files);
// 读取文件修改
files.forEach(file {const oldPath __dirname /code/ file;// 利用正则表达式_前面是一位数的补0const newFileName file.replace(/^(\d)_(.)$/i, 0$1_$2);const newPath __dirname /code/ newFileName;//重命名fs.renameSync(oldPath, newPath);
})path模块 path模块提供了操作路径的功能。 常用API如下
API说明path.resolve拼接规范的绝对路径 常用path.sep获得操作系统的路径分隔符path.parse解析路径并返回对象path.basename获得路径基础名称path.dirname获得路径目录名path.extname获得路径扩展名
resolve(重点掌握)
代码示例
// path模块
const fs require(fs);
const path require(path);
// 写入文件
// 建议绝对路径 拼接 相对路径 写法 path.resolve(绝对路径相对路径)
fs.writeFileSync(path.resolve(__dirname, ./test.txt), peace and love);
// 不建议这样写 最好不要 绝对路径绝对路径写法 /path为绝对路径
// 这样写的意思是 /path的绝对路径 拼接 ./test.txt
// fs.writeFileSync(path.resolve(__dirname, /path, ./test.txt), peace and love);
运行命令
node ./path/path.jssep sep分隔符 不同操作系统的分隔符不同获取不同操作系统下的分隔符 操作系统分隔符windows\linux/macos/
代码示例
const path require(path);
// sep分隔符 不同操作系统的分隔符不同获取不同操作系统下的分隔符
console.log(path.sep); //windows:\ linux:/ macos:/path
解析路径返回对象》语法: path.parse(path)
参数说明
path:文件解析路径
代码示例
// parse 解析路径并返回对象
// 查看当前文件路径
console.log(__filename);
//定义路径
let str /Users/lhm/Documents/nodejs/path/path.js
// 解析路径
console.log(path.parse(str));basename
获得文件名》语法: path.basename(path)
参数说明
path:文件解析路径
代码示例
// basename 获取路径名称
// 查看当前文件路径
console.log(__filename);
//定义路径
let str /Users/lhm/Documents/nodejs/path/path.js
// 获取的文件名
console.log(path.basename(str)); //path.jsdirname
获得文件夹的目录名》语法: path.dirname(path)
参数说明
path:文件解析路径
代码示例
// dirname 获取文件目录名
// 查看当前文件路径
console.log(__filename);
//定义路径
let str /Users/lhm/Documents/nodejs/path/path.js
// 获取文件目录名
console.log(path.dirname(str)); // /Users/lhm/Documents/nodejs/pathextname
获得文件扩展名即为后缀名》语法: path.extname(path)
参数说明
path:文件解析路径
代码示例
// extname 获取文件扩展名即为后缀名
// 查看当前文件路径
console.log(__filename);
//定义路径
let str /Users/lhm/Documents/nodejs/path/path.js
// 获取文件扩展名
console.log(path.extname(str)); // .jsHTTP协议
初识
全称 Hypertext Transfer Protocol 超文本传输协议 互联网应用最广泛的协议之一协议双方必须共同遵从的一组约定浏览器 输入 url 给服务器发送 请求报文 服务器 给 浏览器 发送响应报文 进行响应
HTTP报文
安装软件fiddler 查看报文内容自行下载摸索。
请求报文结构
请求行 GET https://www.baidu.com请求头请求体
请求行 如 GET https://www.baidu.com/ HTTP/1.1 构成
请求方法URLHTTP版本号
请求方法
常见方法如下
方法作用GET主要用于获取数据POST主要用于新增数据PUT/PATCH主要用于更新数据DELETE主要用于删除数据HEAD/OPTIONS/CONNECT/TRACE使用相对较少
URL 全程 Uniform Resource Locator 统一资源定位符 比如https://search.jd/com:443/search?keywordonepluspsort12 协议名 https主机名 search.jd.com端口号 443路径 /search查询字符串 ?keywordonepluspsort12
HTTP版本号 常见版本号
版本号发布时间1.01996年1.11999年22015年32018年
请求头 很多键值对组成主要是记录浏览器很多相关的信息记录与浏览器交互的行为。 点击跳转MDN查看请求头
请求体 用一个场景理解它。比如登录场景 ,发送post请求传过去的数据:username111passwordasaj11212。这些即为请求体。 响应报文
响应行响应头响应体
响应行
HTTP版本号响应状态码响应状态的描述
响应状态码
状态码含义200请求成功403禁止请求404找不到资源500服务器内部错误
响应状态的描述 响应状态的描述通常与状态码相关 状态码状态描述200OK403Forbidden404Not Found500Internal Server Error
点击查看更多状态码
响应头 跟请求头一样为键值对的形式记录与服务器相关的一些内容。 点击查看更多响应头
响应体 响应体即响应的内容 常见的响应体格式有
HTMLCSSJavaScript图片视频JSON
网络基础概念
IP IP也称为[IP地址]本身是一个数字标识。例如 192.168.1.3。 通俗理解IP地址主要用来寻找网络设备本身是32Bit的二进制数字。 作用
IP用来标识网络中的设备实现设备间的通信
IP的分类
类型说明本地回环IP地址127.0.0.1 ~ 127.255.255.255局域网IP私网IP)192.168.0.0 ~ 192.168.255.255172.16.0.0~172.31.255.25510.0.0.0 ~ 10.255.255.255广域网公网IP)除上述之外
端口 端口应用程序的数字标识。一台现代计算机有65536个端口0~65535。一个应用程序可以使用一个或多个端口。 通俗理解 赶集的摊位的 编号 好比 计算机理解的端口 作用
实现不同主机应用程序之间的通信
http模块
创建http服务端
代码示例./http/createServer.js
// 创建服务
// 1.导入http模块
const http require(http);
// 2.创建服务对象
const server http.createServer((request, response) {//设置响应内容response.end(Hello World! Hello node.js Server!);
});
// 3.监听端口启动服务
server.listen(9000, () {console.log(Server started on port 9000...);console.log(http://localhost:9000/);
})注意事项
命令行ctrl c停止服务当服务启动后更新代码必须重启服务才能生效响应内容中文乱码的解决方法
response.setHeader(content-type,text/html;charsetutf-8)端口号被占用
关闭当前正在运行监听端口的服务使用较多修改其他端口号
HTTP协议默认端口号是80。HTTP服务开发常用端口有3000,8080,8090,9000等
获取http请求报文
想要获取请求的数据需要通过request对象
含义语法重点掌握请求方法request.method*请求http协议版本request.httpVersion请求路径request.url*请求头request.headers*请求体request.on(‘data’,function(chunk){})request.on(‘end’,function(){});url请求路径const url require(‘url’); url.parse(request.url).pathname;*url查询字符串const url require(‘url’); url.parse(request.url,true).query;
注意事项
request.ur;只能获取路径以及查询的字符串无法获取URL中的域名以及协议的内容request.headers将请求信息转化为一个对象并将属性名都转换成了【小写】关于路径如果访问网站的时候只写了IP地址或者是域名信息此时请求的路径为【/】关于favicon.ico这个请求是属于浏览器自动发送的请求
请求头
代码示例./http/request_header.js
ps:浏览器打开form.html输入提交进行测试 ps:当端口被占用关闭其它运行9000端口的终端或者修改运行端口号。
// 请求报文之请求头//引入http模块
const http require(http);
//创建服务对象
const server http.createServer((request, response) {// 1-----请求头//请求方法console.log(请求方法);console.log(request.method);// 请求http版本console.log(请求http版本);console.log(request.httpVersion);// 请求头console.log(请求url);console.log(request.headers.host);// 请求路径console.log(请求路径);console.log(request.url);
})
//启动服务
server.listen(9000, () {console.log(server listening on port 9000,);console.log(http://localhost:9000/);
})
请求体
代码示例./http/request_content.js
ps:浏览器打开form.html输入提交进行测试 ps:当端口被占用关闭其它运行9000端口的终端或者修改运行端口号。
// 请求报文之请求体//引入http模块
const http require(http);
//创建服务对象
const server http.createServer((request, response) {// ----请求体// 定义请求体内容let body ;request.on(data, (chunk) {body chunk;})request.on(end, () {console.log(请求体内容)console.log(body);console.log(--------end--------------)response.end(hello world!);})
})
//启动服务
server.listen(9000, () {console.log(server listening on port 9000,);console.log(http://localhost:9000/);
})
请求路径与查询关键字
方式1通过内置url解析
请求路径语法url.parse(request.url).pathname)查询字符串语法url.parse(request.url,true).query
注意事项 2. 运行当端口被占用关闭其它运行9000端口的终端或者修改运行端口号。 2. 在浏览器输入进行测试观察终端打印日志点击跳转浏览器进行测试
代码示例./http/request_url.js
// 请求报文之url//引入http模块
const http require(http);
const url require(url);
//创建服务对象
const server http.createServer((request, response) {// ----urlconsole.log(请求路径)console.log(url.parse(request.url).pathname);console.log(查询字符串)console.log(url.parse(request.url,true).query);console.log(url.parse(request.url,true).query.username);console.log(url.parse(request.url,true).query.password);console.log(---------------);response.end(hello world!);
})
//启动服务
server.listen(9000, () {console.log(server listening on port 9000,);console.log(http://localhost:9000/);
})
方式2通过new URL解析 语法new URL(input[,base]) 点击了解更多new URL英文 点击了解更多new URL中文
注意事项
运行当端口被占用关闭其它运行9000端口的终端或者修改运行端口号。在浏览器输入进行测试观察终端打印日志点击跳转浏览器进行测试
代码示例./http/request_newURL.js
// 请求报文之url//引入http模块
const http require(http);
//创建服务对象
const server http.createServer((request, response) {// 2- 通过new URL方式获取let url new URL(request.url, http://localhost:9000);console.log(url);console.log(请求路径)console.log(url.pathname);console.log(查询字符串);console.log(url.searchParams.get(username));console.log(------------------)
})
//启动服务
server.listen(9000, () {console.log(server listening on port 9000,);console.log(http://localhost:9000/);
})
http请求练习
注意事项
运行当端口被占用关闭其它运行9000端口的终端或者修改运行端口号。在浏览器输入进行测试观察终端打印日志
登录页面点击跳转浏览器进行测试注册页面点击跳转浏览器进行测试不存在点击跳转浏览器进行测试
/** http练习* 需求* 请求类型 get 地址/login 返回 “登录页面” 四字* 请求类型 get 地址/reg 返回 “注册页面” 四字*/
const http require(http);
const server http.createServer((req, res) {if (req.method GET) {let url new URL(req.url, http://127.0.0.1:9000);//设置中文防止乱码res.setHeader(Content-Type, text/html; charsetUTF-8);if (url.pathname /login) {res.end(登录页面);} else if (url.pathname /reg) {res.end(注册页面);} else {res.end(您当前访问页面不存在);}} else {res.end(您当前访问页面不存在);}
});
server.listen(9000, () {console.log(Server started on port 9000,);console.log(http://localhost:9000,);
})设置http响应报文
作用语法设置响应状态码response.statusCode设置响应状态描述response.statusMessage(用的非常少设置响应头信息response.setHeader(‘头名’,‘头值’)设置响应体response.write(‘xx’);response.end(‘xx’);
注意事项
运行当端口被占用关闭其它运行9000端口的终端或者修改运行端口号。在浏览器输入此url进行请求打开浏览器——右键检查——查看网络
点击跳转浏览器进行测试
代码示例
// 设置响应头//引入http模块
const http require(http);
//创建服务对象
const server http.createServer((request, response) {// 设置响应//响应状态码response.statusCode 200;//设置响应状态信息response.statusMessage iloveyou;// 设置响应头// 设置编码格式 防止中文乱码response.setHeader(content-type, text/html; charsetutf-8);// 自定义响应头response.setHeader(myHeaders, Authorization);//响应体 write可有多个response.write(哈哈哈哈 响应体);response.write(哈哈哈哈2 响应体);// 响应体 end 只有一个response.end(bye!!)
});
//启动服务
server.listen(9000, () {console.log(server listening on port 9000,);console.log(http://localhost:9000/);
})
http响应练习
注意事项
运行当端口被占用关闭其它运行9000端口的终端或者修改运行端口号。在浏览器输入此url进行请求查看效果
点击跳转浏览器进行测试
代码示例res.pratice.html res_pratice.js
/** http响应练习* 需求* 搭建http服务响应一个4行3列的表格* 并且要求表格有 隔行换色效果且点击单元格能高亮显示*/
const fs require(fs);
const http require(http);
const server http.createServer((req, res) {res.setHeader(content-type, text/html;charsetUTF-8);const html fs.readFileSync(__dirname/res_pratice.html);res.end(html);
});
server.listen(9000, () {console.log(Server started on port 9000,);console.log(http://localhost:9000/);
})
网页资源加载的全部过程 1-先加载html 2-再根据html内容加载css、图片资源、js等 3-favicon.icon请求浏览器默认行为默认请求网站图标favicon.icon 4-ws请求插件行为使得网页实现自动刷新功能
实现网页引入外部资源 接回之前的响应练习现在需求是将css js分离开单独引入资源 代码示例: res_pratice.js 读取res_practice.html res_pratice.css pratice_click.js
/** http响应练习* 需求* 搭建http服务响应一个4行3列的表格* 并且要求表格有 隔行换色效果且点击单元格能高亮显示*/
const fs require(fs);
const http require(http);
const server http.createServer((req, res) {//按路径区分 请求资源 进行 响应。不要都响应此htmlconst {pathname} new URL(req.url, http://127.0.0.1)if (pathname /) {//注意此响应头得在html里否则可能会没效果res.setHeader(content-type, text/html;charsetUTF-8);const html fs.readFileSync(__dirname /res_pratice.html);res.end(html);} else if (pathname /res_pratice.css) {const css fs.readFileSync(__dirname /res_pratice.css);res.end(css);} else if (pathname /pratice_click.js) {const js fs.readFileSync(__dirname /pratice_click.js);res.end(js);} else {res.end(h1404 Not Found!/h1);}});
server.listen(9000, () {console.log(Server started on port 9000,);console.log(http://localhost:9000/);
})
静态资源与动态资源
静态资源内容长时间不发生改变的资源例如图片视频css文件js文件HTML文件字体文件等动态资源内容经常更新的资源例如百度首页网易首页京东搜索列表页面等。
搭建静态资源服务
对响应式练习的优化处理
利用__dirnamepathname进行拼接,无需多次请求
代码示例
/** http响应练习* 需求* 搭建http服务响应一个4行3列的表格* 并且要求表格有 隔行换色效果且点击单元格能高亮显示*/
const fs require(fs);
const http require(http);
const server http.createServer((req, res) {//按路径区分 请求资源 进行 响应。不要都响应此html// const {pathname} new URL(req.url, http://127.0.0.1)// if (pathname /) {// //注意此响应头得在html里否则可能会没效果// res.setHeader(content-type, text/html;charsetUTF-8);// const html fs.readFileSync(__dirname /res_pratice.html);// res.end(html);// } else if (pathname /res_pratice.css) {// const css fs.readFileSync(__dirname /res_pratice.css);// res.end(css);// } else if (pathname /pratice_click.js) {// const js fs.readFileSync(__dirname /pratice_click.js);// res.end(js);// } else {// res.end(h1404 Not Found!/h1);// }// 优化const {pathname} new URL(req.url, http://127.0.0.1)const filename pathname / ? __dirname /res_pratice.html : __dirname pathname;fs.readFile(filename, utf8, (err, data) {if (err) {res.end(h1404 Not Found!/h1);console.error(err);return;}res.end(data);})
});
server.listen(9000, () {console.log(Server started on port 9000,);console.log(http://localhost:9000/);
})
网页URL之绝对路径
绝对路径可靠性强而且相对性容易理解在项目中运用较多
形式特点http://www.baidu.com直接向目标资源发送请求容易理解。网站的外链会用到此形式。//www.baidu.com与页面URL的协议拼接形成完整URL再发送请求。大型网站用的比较多/web与页面URL的协议、主机名、端口拼接形成完整URL再发送请求。中小型网站
网页URL之相对路径
相对路径在发送请求时需要与当前页面URL路径进行计算得到完整URL后再发送请求学习阶段用的较多。 例如当前网页url为http://www.atguigu.com/course/h5.html
形式最终的URL./css/app.csshttp://www.atguigu.com/course/css/app.cssjs/app/jshttp://www.atguigu.com/course/js/app.js…/img/logo.pnghttp://www.atguigu.com/img/logo.png…/mp4/show.mp4http://www.atguigu.com/mp4/show.mp4
网页中使用URL的场景小结
包括但不限于以下场景
a标签hreflink标签hrefscript标签srcimg标签srcvideo audio 标签 srcform中的actionAJAX请求中的URL
设置mime类型
媒体类型 通常称为Multipurpose Internet Mail Extension 或 MIME 类型是一种标准用来表示文档、文件或字节流的性质和格式。
mime 类型结构 [type]/[subType]
例如 text/html images/jpeg image/png application/jsonHTTP服务可以设置响应头Content-Type来表明响应体的MIME类型浏览器会根据该类型决定如何处理资源 下面是常见的文件对应的mime类型
html: text/html
css:text/css
js:text/javascript
png:images/png
jpg:images/jpeg
gif:images/gif
mp4:video/mp4
mp3:audio/mpeg
json:application/json对于未知的资源类型可选择application/actet-stream类型浏览器在遇到该类型响应时会对该响应体类型进行独立存储也就是我们常见的下载效果 代码示例./http/mime.js
// 设置mime
const http require(http);
const path require(path);
const server http.createServer((req, res) {// 优化const {pathname} new URL(req.url, http://127.0.0.1);const filepath pathname / ? __dirname /res_pratice.html : __dirname pathname;// 得到后缀名const extname path.extname(filepath).slice(1);// 根据请求文件后缀名设置相应的mimelet mimes {html: text/html,css: text/css,js: text/javascript,png: images/png,jpg: images/jpeg,gif: images/gif,mp4: video/mp4,mp3: audio/mp3,json: application/json}// 获取对应类型const type mimes[extname];// 判断if (type) {//解决乱码问题 if(extnamehtml){res.setHeader(Content-Type, type;charsetutf-8);}else{res.setHeader(Content-Type, type);}} else {res.setHeader(Content-Type, application/actet-stream);}fs.readFile(filepath, utf8, (err, data) {if (err) {res.end(h1404 Not Found!/h1);console.error(err);return;}res.end(data);})
});server.listen(9000, () {console.log(server started);console.log(http://localhost:9000/);
})解决乱码问题
html添加字符集charset:utf-8即可.响应头的字符集优先于html的meta设置的字符集
代码示例如上./http/mime.js
完善错误处理
点击node.js中文网查看错误代码具体含义
代码处理示例error.js
// 完善错误处理
const http require(http);
const fs require(fs);
const server http.createServer((req, res) {// 优化const {pathname} new URL(req.url, http://127.0.0.1);const filepath pathname / ? __dirname /res_pratice.html : __dirname pathname;fs.readFile(filepath, utf8, (err, data) {if (err) {console.error(err);switch (err.code) {case ENOENT:res.statusCode 404;res.end(h1404 Not Found!/h1);case EPERM:res.statusCode 403;res.end(h1403 Forbidden!/h1);default:res.statusCode 500;res.end(h1Internal Server Error/h1);}return;}res.end(data);})
});server.listen(9000, () {console.log(server started);console.log(http://localhost:9000/);
})
GET和POST使用场景
GET请求场景
在地址栏直接输入url访问点击a链接link标签引入cssscript标签引入jsvideo与audio引入多媒体img标签引入图片form标签中的method为get
POST请求中的请求
form标签中的method为postAJAX中的post请求
GET和POST请求区别
GET和POST是HTTP协议请求中的两种方式主要有以下区别
作用GET主要是用来获取数据POST主要是用来提交数据参数位置GET主要用来获取数据POST主要用来提交数据安全性POST请求相对GET安全一些因为在浏览器中会暴露在地址栏GET请求大小有限制一般为2k,而POST请求则没有大小限制
模块化
什么是模块化 将一个复杂的程序文件依据一定规则规范拆分成多个文件的过程称之为模块化 其中拆分出的每个文件就是一个模块。模块内部的数据是私有的不过模块可以暴露内部数据以使其它模块使用 模块化项目 编码时按照模块一个个编码的整个项目就是一个模块化的项目
模块化好处
防止命名冲突高复用性高维护性
模块化初体验
Commonjs规范
代码示例me.js
// 声明函数
function tiemo(){console.log(timemo)
}
module.exports tiemo;
代码示例index.js
//引入模块
const tiemo require(./me);
// 调用
tiemo();
运行
./module/index.js 是相对于当前打开终端的目录路径根据自己路径找到index.js
node ./module/index.js模块暴露数据
方式1module.exports value方式2module.exports {value1,value2}方式3export.name value
注意不要直接exports value ❎ 错误写法
代码示例 me.js
// 声明函数
function tiemo() {console.log(timemo)
}function niejiao() {console.log(niejiao);
}// 暴露数据
// module.exports tiemo;
// 暴露数据2
module.exports {tiemo,niejiao
}
// 暴露数据3
// exports.niejiao niejiao;
// exports.tiemo tiemo;// 注意不能使用 exportsvalue的形式暴露数据
// 因为如下相等
// exports module.exports {tiemo: tiemo}
// exports.tiemo tiemo;
代码示例index.js 调用
//引入模块
const me require(./me);
// 调用
me.tiemo();
me.niejiao();导入模块
在模块中使用require传入文件路径即可使用文件
const test require(./me.js);require使用的一些注意事项
对于自己创建的模块导入时路径建议写相对路径不能省略./和../js和json文件导入时可以不用写后缀c/c编写的node扩展文件也可不写后缀但一般用不到如果导入其他类型的文件会以js文件进行处理如果导入路径为文件夹首先会检测package.json文件中main属性对应的文件如果main属性不存在或者package.json不存在则会检测文件夹下的index.js和index.json.如果还是没找到就会报错导入node.js内置模块时直接require模块的名字即可无需加./和../ Node.js实现了CommonJS模块化规范 导入模块的基本流程
介绍require导入自定义模块的基本流程
将相对路径转为绝对路径定位目标文件缓存检测读取目标文件代码包裹为一个函数并执行自执行函数。通过arguments.callee.toString()查看自执行函数缓存模块的值返回module.exports值
CommonJS规范
module.exports exports 以及require 这些都是CommonJS模块化规范中的内容Node.js是实现了CommonJS模块化规范二者关系有点像JavaScript与ECMAScript
包管理工具 包管理工具就像哆啦A梦 介绍 【包】英文单词 package 代表了一组特定功能的源码集合 包管理工具 管理【包】的应用软件可以对【包】进行下载安装更新删除上传等操作
常用的包管理工具
npmyarncnpm
npm安装与介绍 node.js在安装时会自动安装npm,若你已经安装了node.js,可以直接使用npm 通过 npm -v查看版本号测试。显示版本号即为成功反之失败
npm初始化包
我在此新建了npm文件夹并切换终端目录到npm使用cd npm切换到npm文件夹也可。
npm init (根据问题回答~使用默认就回车)
注意
中文和英文大写命名不允许默认是文件夹的名称所以文件夹也不能用中文和大写version版本号要求x.x.x形式定义x必须是数字,默认值1.0.0ISC证书与MIT证书功能上是相同的关于开源证书扩展阅读点击查看package.json可以手动创建以及修改使用npm init -y 或者npm init --yes 极速创建package.json
搜索包
方式2种
命令行 【npm s/search 关键字】网站搜索 网址是https://www.npmjs.com 关于如何精准找到需要的包 这个事情需要在实践中不断积累通过看文章看项目去学习积累 下载依赖包
npm install 简写 npm i
require导入npm包基本流程
在当前文件夹的node_modules中寻找同名的文件夹在上级目录下的node_modules中寻找同名的文件夹直至找到磁盘根目录
生产环境与开发环境
开发环境是程序员 专门用来写代码 的环境一般是指程序员的电脑开发环境的项目一般只能是程序员自己访问生产环境是项目代码正式运行的环境一般是指正式的服务器电脑生产环境的项目一般每个客户都可以访问
生产依赖与开发依赖
我们可以在安装时设置区分依赖的类型目前分为两类
类型命令补充生产依赖npm i -S uniqnpm i --save uniq-S等效于–save -S是默认选项包信息保存在package.json中的dependencies属性开发依赖npm i -D lessnpm i --save-dev less-D等效于–save-dev -S是默认选项包信息保存在package.json中的devDependencies属性 比如蛋炒饭需要 大米 油 葱 鸡蛋 锅 煤气 铲子 其中 锅 煤气 铲子 属于开发依赖只在制作阶段使用 而大米 有 葱 鸡蛋属于生产依赖 在制作与最终食用都会用 所以开发依赖是只在开发阶段使用的依赖包而生产依赖是开发阶段和最终上线运行阶段都用到的依赖包 npm全局安装
npm i -g nodemon全局安装完成之后就可以在命令行的任何位置运行nodemon命令 该命令作用是自动重启node应用程序。【修改文件代码后不需关闭终端重新运行会自动监测编译】 使用nodemon运行即可
nodemon ./fs/fs_writeFile.js与此同时修改./fs/fs_writeFile.js文件会自动编译不需要关闭重新运行
注意
全局安装命令不受工作目录位置影响可以通过npm root -g 查看全局安装包位置只有全局类的工具才适合全局安装
环境变量path 命令行输入命令会在当前目录寻找.exe或者.cmd后缀可执行文件执行找到执行找不到则报错。 比如输入QQ 会在当前文件夹寻找 QQ.exe或者QQ.cmd的可执行文件。找不到就去环境变量中找所以路径需配置在环境变量中。 安装所有依赖
npm i / npm install
npm inpm安装指定版本的包
语法npm i 包名版本包 示例
npm i jquery1.11.2npm删除包
npm remove / npm rnpm uninstall / npm uni 全局删除示例
npm remove -g modemon局部删除示例
npm remove uniqnpm uninstall juerynpm命令配置别名
通过package.json中配置script npm start 是项目中常用命令用来启动命令。可不加 runnpm run 有自动向上级目录查找的特性跟require函数一样默认对于陌生项目我们可以先通过查看scripts属性来参考项目的一些操作。可看到怎么运行项目、打包项目等 示例如配置了start启动命令
{name: test,version: 1.0.0,description: 学习npm,main: index.js,scripts: {test: echo \Error: no test specified\ exit 1,start: node ./test.js},author: ,license: ISC,dependencies: {uniq: ^1.0.1}
}2.运行
npm run startcnpm
介绍
cnpm淘宝搭建的npmjs.com的完整镜像也称为【淘宝镜像】网址cnpm服务部署在国内阿里云服务器上可以提高的下载速度官网也提供了一个全局工具包cnpm,操作命令与npm大体相同
安装
npm install -g cnpm --registryhttps://registry.npmmirror.com操作命令
基本跟npm相同
功能命令初始化cnpm init安装包cnpm i uniqcnpm i -S uniqcnpm i -D uniqcnpm i -g nodemon安装项目依赖cnpm i删除cnpm r uniqcnpm uni uniq
配置淘宝镜像
用npm可直接下载淘宝镜像配置方式有两种
直接配置工具配置
直接配置
npm config set registry https://registry.npmmirror.com/工具配置
安装nrm
npm i -g nrm修改镜像
nrm use taobao检查是否配置成功
npm config listPS: 检查registry地址是否为https://reggistry/npmmirror.com/ 如果是则表明成功 补充说明: 建议使用第二种方式进行镜像配置因为后续修改起来会比较方便虽然cnpm可以提高速度但是npm也可以通过淘宝镜像进行加速所以npm使用率还是高于cnpm yarn
介绍 yarn是Facebook在2016年推出的JavaScript推出的包管理工具 官网网址 特点
速度超快:yam 缓存了每个下载过的包所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率因此安装速度更快超级安全:在执行代码之前yarn 会通过算法校验每个安装包的完整性超级可靠:使用详细、简洁的锁文件格式和明确的安装算法yarn 能够保证在不同系统上无差异的工作
安装
npm i -g yarnyarn常用命令
功能命令初始化yarn init / yarn init -y安装包yarn add uniq 生产依赖yarn add less --dev 开发依赖yarn global add nodemon 全局安装安装项目依赖yarn删除yarn remove uniq 删除项目依赖包yarn global remove nodemon 全局删除包运行命令别名yarn 别名
npm 和 yarn 选择
大家可以根据不同场景进行选择
个人项目根据个人喜好选择公司项目根据项目代码选择可以选择通过锁文件判断项目的包管理工具
npm 锁文件是 package-lock.jsonyarn 锁文件是 yarn.lock 包管理工具不要混用切记切记切记 npm发布一个包
创建与发布 将自己开发的工具包发布到npm服务上方便自己和其它开发者进行使用操作步骤如下 创建文件夹并创建文件main中index.js入口文件在文件中声明删除使用module.exports暴露
代码示例
function add(a, b) {return a b;
}module.exports {add
}npm初始化工具包npm initpackage.json填写包的信息包名必须唯一注册账号激活账号一定要激活账号修改为官方镜像
之前使用了别的镜像比如淘宝镜像加速不切回官方镜像很可能会上传失败. 通过nrm方式切回官方镜像 没安装的先安装 npm i -g nrm切回官方镜像: nrm use npm登录npm,按照要求登录
npm login提交发布包
npm publish更新包
更新包中代码测试代码是否可用修改package.json中版本号发布更新
npm publish删除包
npm unpublish不成功加上--force强制删除
npm unpublish --force删除包需要一定条件查看条件
你是包作者发布小于24小时大于24小时后没有其他包依赖并且每周小于300下载量并且只有一个维护者
包管理工具扩展介绍 很多语言都有包管理工具。除了编程语言操作系统层面也存在包管理工具。 语言包管理工具PHPcomposerPythonpipJavamavenGogo modJavaScriptnpm/yarn/cnpm/otherRubyrubyGems
操作系统也存在包管理工具不过这个包指的是软件包:
操作系统包管理工具网址Centoscomposerhttps://package.debian.org/stabel/Ubuntuapthttps://package.ubuntu.com /MacOShomeviewhttps://brew.sh /Windowschocolateyhttps://chocolatey.org
nvm介绍与使用
介绍 nvm 全称 Node Version Manager 顾名思义用来管理node版本工具。方便切换不用版本的Node.js。一般项目中新旧项目要求的node版本不同建议使用nvm安装node.js,方便切换 下载安装 安装太久不知道哪个博文好使了可以去网上寻找细致教程 windows的github下载地址选择 nvm-setup.exe 下载即可
常用命令
命令说明nvm use available显示可下载的Node.js版本nvm list显示已安装的版本nvm install 18.12.1安装18.12.1版本的Node.jsnvm install latest安装最新版本的Node.jsnvm uninstall 18.12.1删除18.12.1版本的Node.jsnvm use 18.12.1切换18.12.1的Node.js
express
express介绍 官网介绍expresss是一个基于Node.js平台的极简、灵活的WEB应用开发框架。官网网址.简单来说express是一个封装好的工具包封装了很多功能便于我们开发WEB应用。HTTP服务 http模块帮助我们搭建http服务给浏览器做出相应服务端的功能直接使用还是不太方面于是我们借助express框架. express路由 路由确定了应用程序如何响应客户对特定端点的请求。 express依旧兼容之前的http的获取请求及其响应方法
路由基本使用
一个路由有请求方法、路径和回调函数组成 express中提供了一系列方法可以很方便的使用路由 使用格式如下
app.method(path,callback)PS:代码中1-4方法使用知识点
代码示例startlearn.js
// 初认识express
// 引入模块
const express require(express);
// 创建应用对象
const app express();
const port 3000;
// 1-创建路由 get方法
app.get(/home, (req, res) {res.end(hello world);
})// 2-创建路由 get方法
app.post(/login, (req, res) {res.end(hello login);
})//3- 无论get或post方法
app.all(/test, (req, res) {res.end(no matter methods);
})//4-上面匹配不上的路由规则
app.all(*, (req, res) {res.end(404 No Found);
})//监听端口 启动服务
app.listen(port, () {console.log(Express server started);console.log(http://localhost:9000/);
})
获取请求报文参数
说明原生http获取express框架获取获取请求路径pathconst url require(‘url’); url.parse(request.url).pathname; / new URL(req.url,‘http://localhost:9000’).pathnamereq.path获取请求参数const url require(‘url’); url.parse(request.url,true).query;req.query获取ipreq.connection.remoteAddressreq.ip获取请求头req.headers[‘host’]req.get(‘host’)
获取路由参数
语法eg》路径/:id 通过req.params.id获取路由参数
代码示例
const express require(express);
const app express();
//通配符 通过http://localhost:3000/login/1212121访问即可知
app.get(/login/:id, (req, res) {
// 获取id
console.log(req.params.id);
res.end(login success!);
})
app.get(/, (req, res) {
res.end(hello);
})
//监听端口 启动服务
app.listen(3000, () {
console.log(Express server started);
console.log(http://localhost:3000);
})路由参数练习
运行后点击测试 代码示例如下singer.json params_pratice.js
/** 需求* 通过路由id返回歌手名称及其它名称*/
const express require(express);
const app express();
const fs require(fs);
// 读取歌手假数据json文件
const singersData fs.readFileSync(__dirname /singers.json).toString();
app.get(/singer/:id, (req, res) {const {id} req.params;const matchData JSON.parse(singersData).singers.find(item item.id Number(id));res.setHeader(content-type, text/html; charsetutf-8);if (matchData) {res.end(名称${matchData.singer_name},其它名称:${matchData.other_name});} else {res.end(No Such a Singer);}
})app.listen(3000, () {console.log(Express server started);console.log(http://localhost:3000);
})
一般响应设置
设置响应状态码res.status(200)设置请求头res.set(‘asas’,‘aaa’)设置响应内容 res.send(‘你好’)连贯操作res.status(200).set(‘hahaha~’, ‘hhh’).send(‘你好 express’);
代码示例如下
const express require(express);
const app express();
app.get(/, (req, res) {
// //原生响应也兼容
// res.statusCode 200;
// res.statusMessage asasa;
// res.setHeader(hahha, hhh);
// res.write(hello world!);
// res.end(res content);// express设置状态码
// res.status(200);
// // express设置请求头
// res.setset(hahaha~, hhh);
// // express响应内容 做了封装 中文不乱码
// res.send(你好);// 连贯操作res.status(200).set(hahaha~, hhh).send(你好 express);
})app.listen(3000, () {console.log(server started on port 3000);console.log(http://localhost:3000);
});
其它响应设置
设置重定向res.redirect(‘http://www.baidu.com’)下载响应res.download(‘路径’)响应json: res.json({内容)响应文件内容res.sendFile(__dirname‘/home.html’)
// 其它响应
app.get(/other, (req, res) {//1-设置重定向// res.redirect(http://www.baidu.com);// 2-下载响应// res.download(__dirname /singers.json);// 3-响应json// res.json({// singer_name: 林俊杰,// other_name: JJ Lin,// id: 2// });//4-响应文件内容res.sendFile(__dirname /test.html);
})中间件
中间件介绍
本质是一个回调函数可以像回调喊出一样访问 请求对象响应对象
中间件作用
中间件作用就是使用函数封装公共操作简化代码
中间件类型
全局中间件路由中间件
全局中间价
每一个请求到达服务端之后都会执行全局中间件代码
代码示例middleware.js
// 认识中间件
/** 需求* 追加日志记录写入log.txt文件*/
const express require(express);
const app express();
const fs require(fs);
const path require(path);// 全局中间件
// 定义
function recordMiddleWare(req, res, next) {// 判断是否有文件 没有就创建const filePath path.resolve(__dirname, ./log.txt);// 判断文件是否存在如果不存在就创建一个空文件if (!fs.existsSync(filePath)) {fs.writeFileSync(filePath, );}// 获取url和ip地址const {url, ip} req;// 每个请求过来的路由信息都保存到日志记录文件fs.appendFileSync(path.resolve(__dirname, ./log.txt), ${url} ${ip}\r\n);// 调用nextnext();
}// 调用中间件函数
app.use(recordMiddleWare);app.get(/login, (req, res) {res.send(login success!);
})app.listen(3000, () {console.log(server started at port 3000);console.log(http://localhost:3000);
})
路由中间件实践
运行点击测试1运行点击测试2运行点击测试3
代码示例middleware_pratice.js
// 中间件实践
/** 需求* 针对/admin /setting的请求要求URL携带code521参数如未携带提示【暗号错误】*/
const express require(express);
const app express();// 定义中间件
function checkCodeMiddleWare(req, res, next) {// 获取codeconst {code} req.query;if (Number(code) 521) {next();} else {next(【暗号错误】);}
}//调用中间件
app.get(/admin, checkCodeMiddleWare, (req, res) {res.send(admin success!);
})
//调用中间件
app.get(/setting, checkCodeMiddleWare, (req, res) {res.send(setting success!);
})
app.get(/registry, (req, res) {res.send(registry success!);
})
app.get(*, (req, res) {res.send(h1404 Not Found/h1);
})
app.listen(3000, () {console.log(server started at port 3000);console.log(http://localhost:3000);
})
静态资源中间件
根目录下新建public文件夹》新建index.html文件新建index.css文件代码如下
//静态资源中间件请求
app.use(express.static(__dirname /public));运行代码 staticMiddleware.js,下面路径express/staticMiddleware.js为自己运行的文件路径
node express/staticMiddleware.js验证
默认打开index.html可直接查看css文件
完整代码示例
// 静态资源中间件
const express require(express);
const app express();
//静态资源中间件请求
app.use(express.static(__dirname /public));// 监听端口 启动服务
app.listen(3000, () {console.log(Server running on port 3000);console.log(http://localhost:3000);
})静态资源中间件注意事项
index.html为默认打开的资源静态文件与路由规则app.get(‘/’,(){})同时匹配谁先匹配谁就响应看代码顺序路由响应动态资源静态资源中间件响应静态资源
获取请求体数据body-parser
安装
npm i body-parser获取中间件函数
处理queryString格式的请求体:const urlParser bodyParser.urlencoded({extended: false});处理json格式的请求体:const jsonParser bodyParser.json();
// 获取中间件函数
//处理queryString格式的请求体
const urlParser bodyParser.urlencoded({extended: false});
//处理json格式的请求体
const jsonParser bodyParser.json();使用中间件
//获取请求体数据
app.post(/login, urlParser, (req, res) {// 获取请求体数据console.log(req.body);res.send(用户名: req.body.username br/密码: req.body.password);
})完整代码示例bodyParser.js
// body-parse获取请求体
const express require(express);
const bodyParser require(body-parser);
const app express();
// 获取中间件函数
//处理queryString格式的请求体
const urlParser bodyParser.urlencoded({extended: false});
//处理json格式的请求体
const jsonParser bodyParser.json();//响应login页面
app.get(/login, urlParser, (req, res) {res.sendFile(__dirname /login.html);
})
//获取请求体数据
app.post(/login, urlParser, (req, res) {// 获取请求体数据console.log(req.body);res.send(用户名: req.body.username br/密码: req.body.password);
})
app.listen(3000, () {console.log(Express server started);console.log(http://localhost:3000);
})
防盗链
介绍 比如有的图片直接复制地址显示到img是拿不到的说明这个网站做了防盗链处理。判断源是请求头里的referer参数会携带当前域名和协议及其端口进行请求。 实践
完整代码示例
referer.js
const express require(express);
const app express();
// 定义全局防盗链中间件 判断请求头referer
app.use((req, res, next) {const referer req.get(referer);if (referer) {// 实例化const url new URL(referer);const hostname url.hostname;console.log(hostname);if (hostname ! 127.0.0.1) {res.status(404).send(h1404 Not Found/h1);return;}}next();
})
// 读取静态资源
app.use(express.static(__dirname /public));app.listen(3000, () {console.log(Express server listening on port 3000);console.log(http://localhost:3000);
})
publicindex.html
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body
h1测试/h1
img srchttp://127.0.0.1:3000/images/logo.jpeg altlogo
/body
/html
路由模块化(***) 路由功能代码进行拆分 新建文件夹routes新建homeRouter.js创建单独的路由规则
routermodule.js 代码示例
const express require(express);
const userRouter require(__dirname /routes/userRouter.js);
const adminRouter require(__dirname /routes/adminRouter.js);
const app express();app.use(userRouter);
app.use(adminRouter);app.all(*, function (req, res) {res.send(404 Not Found);
})app.listen(3000, () {console.log(server started);console.log(http://localhost:3000);
})
userRouter.js
// user routes
const express require(express);
const router express.Router();
router.get(/login, (req, res) {res.send(login登录);
})
router.get(/registry, (req, res) {res.send(registry注册);
})
module.exports router;
adminRouter.js
// admin routes
const express require(express);
const router express.Router();
router.get(/setting, (req, res) {res.send(设置setting);
})
router.get(/modify, (req, res) {res.send(修改setting);
})
module.exports router;
模版引擎
简单介绍
模版引擎是分离用户界面和业务数据的一种技术
ejs 分离HTML和JS的ejs是一个高效的JavaScript模版引擎。主要了解ejs,现在不多用了。 安装
npm i ejs导入ejs
const ejs require(ejs);使用ejs渲染
代码示例ejs.js
// ejs初体验
const express require(express);
const ejs require(ejs);
const fs require(fs);
const path require(path);const app express();
// 读取静态资源
app.use(express.static(path.join(__dirname, ./public)));const china 中国;
// 读取html文件
const htmlData fs.readFileSync(__dirname /public/index.html,utf-8).toString();
//使用ejs渲染
const result ejs.render(htmlData, {china: china});
console.log(result);
代码示例index.html % china %
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body
h1测试/h1
img srchttp://127.0.0.1:3000/images/logo.jpeg altlogoh1读出来了吗/h1
h2% china %/h2/body
/html
ejs列表渲染
代码如下ejs_xiyou.js
// ejs列表渲染
/** 需求* 渲染ul li 西游数组*/const ejs require(ejs);
const fs require(fs);const xiyou [唐僧, 孙悟空, 沙僧, 猪八戒];
const htmlData fs.readFileSync(__dirname /ejs_xiyou.html).toString()const result ejs.render(htmlData, {xiyou: xiyou});
console.log(result);
代码如下ejs_xiyou.html
ul% xiyou.forEach(item{ %li % item %/li% }) %
/ulejs条件渲染
js如上html如下 代码示例
% if(isLogin){ %
span登录成功/span
% }else{ %
span登录失败/span
% } %express中使用ejs
设置模板引擎
app.set(view engine, ejs);设置模板文件存放位置 新建view文件夹》views新建.ejs文件比如home.ejs
app.set(views,path.resolve(__dirname,./views))render响应
res.render(home,{title})创建模版文件 其实就是.ejs文件但其实就是类html文件,主要得含有如下代码
% title %完整代码示例express_ejs.js
const express require(express);
const ejs require(ejs);
const path require(path);
const app express();
// 1-设置模版引擎
app.set(view engine, ejs);
// 2-设置模版文件存放位置
app.set(views, path.resolve(__dirname, ./views));app.get(/home, (req, res) {const title Home页面;// 3-render响应res.render(home, {title});// 创建模版文件 home.ejs
})app.all(*, (req, res) {res.send(404 Not Found);
})app.listen(3000, () {console.log(Server is running on port 3000);console.log(http://localhost:3000);
});
完整代码viewshome.ejs
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body
h1测试/h1
h1% title % /h1
/body
/html
express-generator工具
通过应用生成器express-generator快速创建一个应用骨架
安装
npx命令来运行包含Node.js8.2.0及更高的版本中
npx express-generatornpm方式
npm i -g express-generator创建文件夹
语法 express -e 文件夹名称
express -e generator查看相关命令
express -h查看文件上传报文
代码示例 portrait.js
const express require(express);
const path require(path);
const app express();
//设置模板引擎
app.set(view engine, ejs);
//设置模板引擎存放文件位置
app.set(views, path.resolve(__dirname, ./views));// render响应
app.get(/portrait, (req, res) {res.render(portrait);
})app.post(/portrait, (req, res) {console.log(req);res.send(成功);
})app.listen(3000, () {console.log(Express server started);console.log(http://localhost:3000);
});
完整代码portrait.ejs
!DOCTYPE html
html langen
headmeta charsetUTF-8title查看文件上传报文/title
/head
body
form action/portrait methodpost enctypemultipart/form-data用户名input typetext nameusernamebr头像 input typefile nameportraitbutton点击提交/button
/form
/body
/html
处理文件上传
借助库formidable 使用参考注意Commonjs 使用require引入需要安装V2版本的V3的只能使用import 引入创建public文件夹》images文件夹
代码示例
const express require(express);
const path require(path);
const formidable require(formidable).formidable;const app express();
//设置模板引擎
app.set(view engine, ejs);
//设置模板引擎存放文件位置
app.set(views, path.resolve(__dirname, ./views));// render响应
app.get(/portrait, (req, res) {res.render(portrait);
})
// 响应静态资源——方便访问上传的图片
app.use(express.static(path.resolve(__dirname, ./public)));app.post(/portrait, (req, res) {const form formidable({multiple: true,// 设置上传文件的保存目录uploadDir: path.join(__dirname, ./public/images),// 保持文件后缀keepExtensions: true})form.parse(req, (err, fields, files) {if (err) {next(err);return;}// 存放非文件的字段// console.log(fields);// 存放文件// console.log(files);// 服务器保存存放的照片的访问urlconst url /images/ files.portrait.newFilename;res.send(url);});})app.listen(3000, () {console.log(Express server started);console.log(http://localhost:3000);
});
mongoDB
介绍 基于分布式文件存储的数据库官方网址 相比于纯文件管理数据数据库管理数据优点
速度更快扩展性更强安全性更强
核心概念
数据库又称数据仓库可存放很多集合集合类似于JS中的数据在集合中可以存放很多文档文档数据库中的最小单位类似JS中的对象
下载安装与启动
下载地址 这边记录下自己的mac安装教程可根据直接的电脑系统去搜搜安装
参考mac安装mongoDB数据库
具体步骤
进入MongoDB官网进行下载下载完毕并且解压重新命名为 【mongodb】文件夹打开访达 按住快捷键commandshiftg 前往/usr/local路径将解压并命名好的【mongodb】文件夹拖入到这个路径下配置环境变量在根目录输入open -e .zshrc打开.zshrc文件夹。注意我的终端是zsh如果你们的终端是bash的话应该输入open .bash_profile在里面添加一下代码
export PATH${PATH}:/usr/local/mongodb/bin保存好了文件后需要执行改文件,在根目录输入 source .zshrc 来进行执行。注意我的终端是zsh如果你们的终端是bash的话应该输入source .bash_profile在此执行一下命令确保是在根目录 不确定就执行 cd ~
mongod --version安装mongodb成功了后那存的数据和日志记录放哪呢。这就需要建立data和log文件夹了。进入到mongodb文件夹的目录下
进行mongodb文件夹下
cd /usr/local/mongodb创建
mkdir data log给这data文件夹赋予读写权限输入电脑开机密码密码输入的时候看不见。
sudo chown [你的用户名] /usr/local/mongodb/data给这log文件夹赋予读写权限输入电脑开机密码密码输入的时候看不见。
sudo chown [你的用户名] /usr/local/mongodb/log在mongondb路径下启动mongoDBmongod --fork --dbpath data --logpath log/mongo.log --logappend 这句命令看到child process started successfully, parent exiting这句话就成功启动服务了
mongod --fork --dbpath data --logpath log/mongo.log --logappend使用mongo指令 浏览器进入http://127.0.0.1:27017/ 关闭数据库服务 直接关闭针对于mac zsh
sudo pkill -f mongod再次访问上面网址就会失败
mac zsh配置启动脚本
创建一个启动脚本文件以确保命令在正确的目录中运行
创建脚本文件
touch start_mongo.sh编辑脚本文件
nano start_mongo.sh添加以下内容
#!/bin/zsh
cd /usr/local/mongodb
mongod --fork --dbpath data --logpath log/mongo.log --logappend
保存并退出 保存文件并退出编辑器按CtrlX退出按Y保存回车enter退出。
PS:同理建立了关闭mongods脚本。 命令为
sudo pkill -f mongod赋予执行权限
chmod x start_mongo.sh运行脚本 现在你可以运行脚本来启动MongoDB
./start_mongo.shmac下载可视化工具Robomongo(studio3T)
下载地址参考可视化工具Robomongo(studio3T)安装使用
文档命令
插入文档
语法db.集合名.insert(文档对象)
db.user.insert({username:ll,age:18})查询文档
语法db.集合名.find(查询条件)
db.user.find({age:20})更新文档
语法db.集合名.update(查询条件,新的文档)
db.user.find({name:张三},{$set:{age:20}})删除文档
语法db.集合名.remove(查询条件)
db.user.remove({name:张三})mongoose
连接数据库
代码及说明如下
// mongoose使用 前提得启动mongoose
// 1-安装依赖
// 2-引入依赖
const mongoose require(mongoose);// 3-连接mongodb服务
mongoose.connect(mongodb://127.0.0.1:27017/user);
// 补充说明1-设置strictQuery为true
mongoose.set(strictQuery, true);// 设置回调
// 连接成功的回调 补充说明2-once事件回调函数只执行一次
mongoose.connection.on(open, () {console.log(连接成功!);
})
// 连接错误的回调
mongoose.connection.on(error, (err) {console.log(连接错误)console.error(err);
})
// 连接关闭的回调
mongoose.connection.on(close, () {console.log(连接关闭);
})// 关闭连接
setTimeout(function () {console.log(连接关闭);mongoose.disconnect();
}, 2000)
…mongoose大致学到这里需要的在看文档好了…
会话控制
介绍 所谓会话控制是对会话进行控制。 因为HTTP是一个无状态的协议它没有办法区分多次的请求是否来自同一客户端无法区分用户而产品中又大量存在这样的需求所以我们需要通过会话控制解决该问题。 常见的会话控制方式
CookieSessionToken
Cookie cookie是HTTP服务器发送到用户浏览器并保存在本地的一小块数据 cookie是保存在浏览器的一小块数据cookie是按照域名划分保存的
特点
浏览器向服务器发送请求时会自动将当前域名可用的cookie设置在请求头中然后传递给服务器。请求头的名字也叫cookie 所以将cookie理解为一个http的请求头也是可以的
浏览器Cookie
禁用cookie 这个操作一般不做 网站——隐私设置和安全性设置——常规设置——阻止所有cookie
删除cookie
网站——隐私设置和安全性设置——清除相应网站数据
查看cookie
edge浏览器查看——输入cookie查询——cookie和网站数据——点击下拉查看谷歌浏览器查看——网站链接旁的左上方小锁——cookie和网站数据——点击查看
express Cookie
设置cookie
eg:res.cookie(‘name’,‘lhm’,{})
const express require(express);
const app express();
app.get(/set-cookie,(req,res){res.cookie(name,lhm);//会在浏览器关闭的时候销毁res.cookie(name,lhm,{maxAge:60 * 1000}); //maxAge最大存活时间 单位毫秒 但是浏览器中存的是秒sres.send(home);
})删除cookie
eg:res.clearCookie(‘name’)
const express require(express);
const app express();
app.get(/remove-cookie,(req,res){res.clearCookie(name);res.send(remove);
})读取cookie
工具库cookie-parse,使用这个为一个cookie解析中间件
安装依赖
npm i cookie-parse引入使用
const express require(express);
const cookieParse require(cookie-parse);
const app express();
app.use(cookieParse());获取cookie值
req.cookies获取到cookie值
app.get(/get-cookie,(req,res){console.log(req.cookies);console.log(res.cookies.name);
})session 保存到服务器的一块儿数据保存当前访问的用户的相关信息 作用 实现会话控制可以识别用户的身份快速获取当前用户的相关信息 运行流程
填写账号和密码校验身份校验填入通过后创建session信息然后通过session_id的值通过响应头返回给浏览器有了cookie,下载发送请求会自动携带cookie,服务器通过cookie和session_id的值确定用户的身份
session与cookie区别
存在位置不同。cookie存在浏览器session 服务端安全性。cookie明文存在客户端session是存在服务器安全性相对较好网络传输量。 cookie设置内容过多会增加保温体积影响传输效率。session数据存储在服务器只是通过cookie传递id,所以不影响传输效率存储限制。cookie保存的数据不超过4k 且单个域名下的存储数量有限。session数据存储在服务器没有限制。
视频的基础知识大致学到这里下面似乎涉及用处小需要的时候还有机会的话再更新吧…
完结撒花~~~