nodeJs核心API
话不多说,直接进入主题 更多内容移步官网nodeJs
fs文件操作
以下文件的路径都是相对路径,会存在问题,后面会有优化
1、文件读取 -- fs.readFile
- readFile有三个参数:
- 参数1:path (被读取文件的路径)
- 参数2:option(读取文件的内容以什么格式被编译,经常使用的是utf-8)
- 参数3:callback (回调函数,读取文件之后的操作,接收两个参数)
- 参数1:Error(读取文件失败的结果)
- 参数2:data(读取文件成功的结果)
const fs = require('fs')
fs.readFile('./1.txt', 'utf-8', function (err, data) {
if (err) return console.log('读取文件失败' + err.message)
console.log('读取文件成功' + data)
})
2、 文件写入 -- fs.writeFile
重复写入不会报错,会覆盖上一次的文件内容
- writeFile有四个参数:
- 参数1:file (被读取文件的路径)
- 参数2:写入文件的内容
- 参数3:option(写入文件的内容以什么格式被编译,默认是utf-8)
- 参数4:callback (回调函数,写入文件之后的操作,接收一个参数)
- 参数:Error(读取文件失败的结果)
fs.writeFile('./2.txt','十月',function (err) {
console.log(err); //null
})
3、文件追加 -- fs.appendFile
追加的文件路径不存在,默认是先创建文件,然后再向文件中追加内容
- appendFile有四个参数:
- 参数1:file (被追加文件的路径)
- 参数2:写入文件的内容
- 参数3:option(写入文件的内容以什么格式被编译,默认是utf-8)
- 参数4:callback (回调函数,写入文件之后的操作,接收一个参数)
- 参数:Error(读取文件失败的结果)
fs.appendFile('./2.txt', '你好', function (err) {
console.log(err) //null
})
4、关于路径的优化__dirname
:
- 使用相对路径,如果实在当前文件夹下执行,不会出现任何问题,如何不在当前文件下执行,会报错(找不到需要执行的文件)
[Error: ENOENT: no such file or directory, open 'D:\demo\file\2.txt'] {
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'D:\\demo\\file\\2.txt'
}
-
解决办法:使用
__dirname
拼接需要执行的文件的路径即可__dirname
:表示当前执行的文件所在的绝对路径
-例子:
fs.appendFile(__dirname+'/file/2.txt', '你好', function (err) {
console.log(err)
})
5、和__dirname
相似的方法__filename
-
__filename理解
:表示当前执行的文件的完整路径:路径中包含了具体的文件名
6、文件的状态fs.stat
fs.stat
有三个参数:- 参数1:被判断文件的路径
- 参数2:返回的 fs.Stats 对象中的数值是否为 bigint 型。 默认值: false。
- 参数3:callback回调函数:其有两个参数
- 参数1:Error 获取文件状态失败的数据
- 参数2:stats:是一个对象,包含了文件的所有状态信息(大小、创建时间、判读是否是文件或者目录等等)
7、文件拷贝fs.copyFile
fs.copyFile
有四个参数:-
参数1:要拷贝的源文件名
-
参数2:拷贝操作的目标文件名。
-
参数3:用于拷贝操作的修饰符。默认值: 0。
-
参数4:callback回调函数,一个参数:Error,拷贝是否成功的返回值
-
path路径操作
1、path.join()
路径拼接:里面的参数是一个个的拼接路径,应用场景:路径拼接,防止路径拼接错误导致工作效率降低,
示例代码
fs.appendFile(path.join(__dirname,'/file/2.txt'), '你好', function (err) { console.log(err) })
2、path.sep
获取系统的分隔符号,windows是/
,linux是\
3、path.basename
获取路径的最后一部分
- 两个参数:
- 参数1:需要获取最后一部分的路径
- 参数2:ext 可选的文件扩展名,当指定了最后一个参数,返回的值就会去除扩展名
4、path.dirname
获取path的目录名,获取的结果是最后一个/
之前的路径,只有一个参数:path路径
5、path,extname
获取文件的扩展名,只接受一个参数path路径
单线程和异步简单介绍
1、重点记住三句话:
-
JavaScript的解析和执行一直是单线程的,但是宿主环境(浏览器或node)是多线程的
-
异步任务是由宿主环境开启子线程完成,并通过事件驱动、回调函数、队列,把完成的任务,交给主线程执行
-
JavaScript解析引擎一直在做一个工作,就是从任务队列里提取任务,放到主线程里执行
模块化规范
1、nodeJs遵循的规范是commonJs,在浏览器端不支持commonJs,因为commonJs下,模块是异步加载的 2、每一个模块都有module、require、exports三个属性 3、模块向外暴露成员,在每一个模块中都是以module.exports为准(推荐) 4、AMD/CMD是commonJs在浏览器端的解决方案,在AMD/CMD下,模块都是异步加载的(现在也不行了) 5、主流的模块化是ES6的模块化,现在成为主流的浏览器和服务器通用的模块解决方案
包的介绍
1、什么是包:
- 英文名叫做 Packages,包是在模块基础上更深一步的抽象;
- 包的目的:方便分发和推广基于 CommonJS 规范实现的 应用程序 或 类库;
- 包可以看作是 模块、代码 和 其它资源 组合起来形成的 独立作用域; 2、规范的包结构
- 包都要以一个单独的目录而存在
- package.json 必须在包的顶层目录下
- package.json 文件必须符合 JSON 格式,并且必须包含如下三个属性:name, version, main
- name: 包的名字
- version: 包的版本号
- main: 表示包的入口文件
- 二进制文件应该在bin目录下;
- javaScript代码应该在lib目录下;
- 文档应该在doc目录下;
- 单元测试应该在test目录下;
- Node.js对包要求并没有那么严格,只要顶层目录下有package.json,并符合基本规范即可; 3、包描述文件 package.json
- name:包的名称,必须是唯一
- description:包的简要说明
- version:符合语义化版本识别规范的版本字符串
- keywords:关键字数据,通常用于搜索
- maintainers:维护者数组,每个元素要包含name、email、web可选字段
- contributors:贡献者数组,格式与maintainers相同。包的坐着应该是贡献者数据的第一个元素
- bugs:提交bug的地址,可以是网址或者电子邮件地址
- licenses:许可证数组,每个元素要包含type和url字段
- repositories:仓库托管地址数组,每个元素要包含type、url和path字段
- dependencies:包的依赖,一个关联数组,由包名称和版本号组成。
- devDependencies:开发依赖项,表示一个包在开发期间用到的依赖项 4、包文件结构:以封装计算器为例
5、npm
包的相关介绍
- 全局安装和本地安装
- 全局安装:安装到计算机全局环境中的包,叫做全局包;安装的全局包可以在当前电脑的任何目录下,直接通过命令行来访问;
- 安装:
npm install 包名
-g - 路径:
C:\Users\用户目录\AppData\Roaming\npm
- 卸载
npm uninstall 包名 -g
- 安装:
- 本地安装:跟着项目安装的包,叫做本地包;本地包都会被安装到 node_modules 目录下;
- 安装:npm i 包名 --save
- 路径:项目根目录下node_moudles
- 卸载:npm uninstall 包名 --save
- 全局安装:安装到计算机全局环境中的包,叫做全局包;安装的全局包可以在当前电脑的任何目录下,直接通过命令行来访问;
npm
常用命令:-
--save 的缩写是 -S
-
--save-dev的缩写是 -D
-
install 的缩写是 i
-
注意:dependencies 节点,表示项目上线部署时候需要的依赖项;devDependencies节点,表示项目在开发阶段需要的依赖项,但是当项目要部署上线了,devDependencies节点中的包,就不再需要了!
-
注意:当使用 npm i快速装包的时候,npm会检查package.json文件中,所有的依赖项,然后都为我们安装到项目中
-
--production 表示只安装 dependencies 节点下,记录的包,不安装devDependencies节点下的包;当项目要上线了,才会使用--production命令
-
node构建服务器
6、node构建服务器
- 创建服务器:使用 const server = http.createServer() 创建服务器;
- 绑定监听事件:通过 server.on('request', function(req, res) { 请求的处理函数 }) 绑定事件 并 指定 处理函数;
- 启动服务器:通过 server.listen(端口, IP地址, 启动成功的回调函数) 来启动服务器;
- 防止响应内容中文乱码问题
- 通过 设置响应报文头的 Content-Type,来指定响应内容的编码类型,从而防止乱码:
res.writeHeader(200, { 'Content-Type': 'text/plain; charset=utf-8'}
- 根据不同的URL返回不同的文本内容
- 使用 req.url 获取客户端请求的URL地址
- 根据不同的URL返回不同的HTML页面
- 主要思路:使用 fs 模块 读取URL对应的HTML页面内容,并使用 res.end() 响应给客户端即可;
- 最终实现的代码
const http = require('http')
const fs = require('fs')
const path = require('path')
const server = http.createServer()
server.on('request', function (req, res) {
// req客户端相关的参数,res表示和服务器相关的参数和方法
let url = req.url
if (url==='/') url='/view/index.html'
fs.readFile(path.join(__dirname,url),function (err,buffer) {
if(err) return res.end('404. Not Found.')
res.end(buffer)
})
})
server.listen(3000, '127.0.0.1', function () {
console.log('服务器运行在 http://127.0.0.1:3000')
})
7、node结合art-template渲染动态页面
art-template
官网:http://aui.github.io/art-template/zh-cn/- 示例项目:初始化项目
npm init
- 安装art-template依赖包:
npm install art-template
- 创建一个js文件,构建一个简单的服务器,同时引入art-template包
- 创建一个html文件,
- 完整代码如下:
- js代码:
const http = require("http");
const template = require("art-template");
const path = require("path");
// 创建服务器
const server=http.createServer()
server.on('request',function (req,res) {
const url=req.url
if (url==='/') {
const htmlStr=template(path.join(__dirname,'./index.html'),{name:'ls',age:'12',aihao:['睡觉','数钱','哈哈']})
res.end(htmlStr)
}
})
server.listen(8080,'127.0.0.1',function () {
console.log('服务器运行在: http://127.0.0.1:8080');
})
- html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>动态渲染</div>
<p>姓名 :{{name}}</p>
<p>年龄 :{{age}}</p>
<p>爱好 :
{{each aihao}}
<span>{{$value}}</span>
{{/each}}
</p>
</body>
</html>
8、nodemon工具的使用
-
作用:能够实时监听当前项目中,文件的变化;只要监听到了文件的变化,则 nodemon 工具,会自动重新启动 web 服务器,从而使最新的代码生效;免去了程序员手动重启服务器的困扰;
-
如何安装:运行 npm i nodemon -g 全局安装即可;
-
如何使用:
- 之前使用 node 要执行的文件路径 来运行 Node.js 代码;
- 现在使用 nodemon 要执行的文件路径 来运行 Node.js 代码;
-
注意:今后在开发Web项目的时候,推荐使用 nodemon 来启动 web 服务器
express框架
9、Node 中开发web项目的框架 - express
express
官网:https://www.expressjs.com.cn/- express 框架的特点:
- 基于Node.js平台之上,进一步封装了 http 模块,从而提供了更好用,更友好的 API
- 使用Express创建网站,比使用原生的http模块更加方便;
- Express 并没有覆盖 原生 http 模块中的方法,而是基于 原生方法之上,做了更友好的封装,让用户体验更好
- express 框架的安装和基本使用
- 安装:运行 npm i express -S 即可安装
- 创建基本的 express 服务器:
- 导入 express 第三方模块;
- 创建服务器的实例:调用 const app = express() 方法;
- 通过 app.get() 或 app.post() 方法,来监听客户端的 get 或 post 请求,具体语法:
- 监听 GET 请求:app.get('请求地址', (req, res) => { 处理函数 })
- 监听 POST 请求: app.post('请求地址', (req, res) => { 处理函数 })
- 启动 express 服务器:通过 app.listen(端口, IP地址, 启动成功后的回调函数) 启动服务器;
- express 中的快捷方法
- res.send()
- 支持 发送 字符串 Content-Type: text/html;
- 支持 发送 对象 或 数组 Content-Type: application/json
- 支持 发送 Buffer 此时会当作文件下载
- res.sendFile()
- 用法1:res.sendFile(path.join(__dirname, './view/index.html'))
- 用法2:res.sendFile('./view/movie.html', { root: __dirname })
- 注意:res.sendFile() 可以向浏览器发送 静态页面;
- res.send()
- express.static() 的静态资源托管
- 语法1: app.use(express.static('public'));
- app.use()方法,是专门用来注册 中间件;
- express.static 是express的内置中间件;
- 语法1: app.use(express.static('public'));
const express = require("express");
const app=express()
// 使用app.use进行中间件的注册
app.use(express.static('./view'))
app.listen(8080,()=>{
console.log('http://127.0.0.1:8080');
})
- 语法2:app.use('/虚拟目录', express.static('public'))
- 在访问的路径前面加上公共的路径
const express = require("express");
const app=express()
// 使用app.use进行中间件的注册
app.use('/page',express.static('./view'))
app.listen(8080,()=>{
console.log('http://127.0.0.1:8080');
})
- 为 express 框架配置模板引擎渲染动态页面(ejs后台引擎)
-
安装 ejs 模板引擎npm i ejs -S
-
使用 app.set() 配置默认的模板引擎 app.set('view engine', 'ejs')
-
使用 app.set() 配置默认模板页面的存放路径 app.set('views', './views')
-
使用 res.render() 来渲染模板页面res.render('index.ejs', { 要渲染的数据对象 }),注意,模板页面的 后缀名,可以省略不写!
-
js代码
-
const express = require("express");
const app=express()
// 使用app.set()设置模板引擎
app.set('view engine', 'ejs')
app.set('views','./ejs_page')
app.get('/',(req,res)=>{
res.render('index.ejs',{name:'zs',age:'20',hobby:['吃饭','睡觉']})
})
app.listen(8090,()=>{
console.log('http://127.0.0.1:8090');
})
- ejs模板引擎代码 :=是输出 <% %>是模板语法格式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
这是用ejs渲染的页面
</div>
<p>
姓名:<%= name %>
</p>
<p>
年龄:<%= age %>
<!-- =是输出 <% %>是模板语法格式 -->
</p>
<% hobby.forEach(item=>{ %>
<p> <%= item %></p>
<% }) %>
</body>
</html>
- 在 express 中配置 art-template
-
安装 两个包 cnpm i art-template express-art-template -S
-
自定义一个模板引擎 app.engine('自定义模板引擎的名称', 渲染函数)
-
将自定义的模板引擎,配置为 express 的默认模板引擎 app.set('view engine', '具体模板引擎的名称')
-
配置 模板页面得存放路径 app.set('views', '路径')
-
js代码
-
const express = require('express');
const app=express()
// html是自定义的模板引擎的名称也是创建模板引擎的后缀名的名称
app.engine('html',require('express-art-template'))
app.set('view engine','html')
app.set('views','./art_page')
app.get('/',(req,res)=>{
res.render('index.html',{name:'ls',age:12,hobby:['1','2','3']})
})
app.listen(8099,()=>{
console.log('http://127.0.0.1:8099');
})
- 模板引擎html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
这是使用art-template渲染的页面
</div>
<div>姓名:{{name}}</div>
<div>年龄{{age}}</div>
{{each hobby}}
<div>
{{$index}}
{{$value}}
</div>
{{/each}}
</body>
</html>
- 使用 express 框架中提供的路由来分发请求(路由的介绍)
- 什么是路由:路由就是对应关系;
- 什么叫做后端路由:前端请求的URL地址,都要对应一个后端的处理函数,那么 这种URL地址到 处理函数之间的对应关系,就叫做后端路由;
- 在Express中,路由的主要职责 就是 把请求分发到对应的处理函数中;
- 在Express中,如何 定义并使用路由呢?
// 1. 封装单独的 router.js 路由模块文件
const express = require('express')
// 创建路由对象
const router = express.Router()
router.get('/', (req, res)=>{})
router.get('/movie', (req, res)=>{})
router.get('/about', (req, res)=>{})
// 导出路由对象
module.exports = router
- express 创建的 app 服务器,如何使用 路由模块呢?
// 导入自己的路由模块
const router = require('./router.js')
// 使用 app.use() 来注册路由
app.use(router)
10、Express 框架里 中间件的概念
- 什么是中间件
- 定义:中间件就是一个处理函数;只不过这个函数比较特殊,包含了三个参数,分别是 req,res,next
注意:中间件方法中的三个参数:
-
req:请求对象;
-
res:响应对象;
-
next:next()可以被调用,表示调用下一个中间件方法;
-
Express 框架中对中间件的5种分类 (了解)
- 应用级别的中间件: 挂载到 app 上的中间件 app.get('URL地址', (req, res, next)=> {});
- 路由级别的中间件: 挂载到 router 对象上的中间件 router.get('url地址', (req, res, next)=>{})
- 错误级别的中间件: 回调函数中,有四个参数 app.use((err, req, res, next)=>{})
- 唯一内置的中间件: express.static()
- 第三方中间件: 非express框架提供的,需要程序员手动安装才能使用的中间件;body-parser 解析post 表单数据
-
自定义解析表单数据的中间件
const express = require("express");
const querystring = require("querystring");
const app=express()
app.use((req,res,next)=>{
let dataStr=''
// 只要客户端向服务器提交了表单,都会触发req的data事件
// 在data事件中可以获取到客户端每次提交过来的不完整的数据
req.on('data',chunk=>{
dataStr+=chunk
})
// 只要req触发了end事件,就表示表单数据提交完毕了,dataStr中存储的数据就是完整的表单数据
req.on('end',()=>{
console.log('结束',dataStr);
// 将获得表单数据格式化,querystring.parse()
let str=querystring.parse(dataStr)
req.body=str
// 注意!在中间件中,最后一定要合理的调用一下next()方法,否则服务器无法结束这次响应
next()
})
})
app.get('/',(req,res)=>{
res.sendFile('./index.html',{root:__dirname})
})
app.post('/formSub',(req,res)=>{
// 拿到从客户端提交的数据
res.send(req.body)
})
app.listen(9090,function () {
console.log('sercer running at http://127.0.0.1:9090');
})
基础的我暂时学到这里,后面会继续更新的