这是我参与「第四届青训营 」笔记创作活动的第4天
node.js
运行node.js
找到需要运行node的文件,然后输入 node 文件名(node server.js)
文件操作
在js中,使用fs模块操作文件,需要用如下方式先引入它
const fs = require('fs')
读取文件
fs.readFile( path[,options], callback )
const fs = require('fs')
fs.readFile('./1.txt', 'utf8', (err, data) => {
if (err) {
console.log('你的文件读取失败')
console.log(err)
return
}
console.log(data)
})
写入文件
fs.writeFile( path, data[,options], callback )
const fs = require('fs')
fs.writeFile('./2.txt', '我喜欢你', (err) => {
if (err) {
console.log('你的文件写入失败')
console.log(err)
return
}
console.log('文件写入成功')
})
路径拼接问题
使用fs模块操作文件,如果提供的路径是./或../开头的相对路径时,会出现路径拼接问题 解决方法:提供一个完整的文件路径
path路径模块
引用path模块
const path = path
path.join()
对路径进行拼接 path.join([...paths])
path.join(__dirname , './2.txt')
path.basename()
返回路径的最后一部分。 第二个参数可以过滤掉文件的扩展名
const path = require('path')
path.basename('/test/something') //something
path.basename('/test/something.txt')//somethingtxt
path.basename('/test/something.txt', '.txt') //something
path.dirname()
返回路径的目录部分
const path = require('path')
path.dirname('/test/something') // /test
path.dirname('/test/something/file.txt') // /test/something
path.extname()
返回路径的扩展名部分
path.extname('/test/something') // ''
path.extname('/test/something/file.txt') // '.txt'
http模块
创建基本的web服务器
//导入http模块
const http = require('http')
//创建web服务器实例
const server = http.createServer()
//为服务器实例绑定request事件,监听客户端请求
server.on('request', (req, res) => {
console.log('received requset')
})
//启动服务器
server.listen(8080, () => {
console.log('server running at http://127.0.0.1:8080')
})
req对象
关于客户端相关数据或属性 req.url 是客户端请求的 url 地址(只包括端口号后面的路径) req.method 是客户端请求的 method 类型
res对象
关于服务器相关数据或属性 res.end() 向客户端发送内容,并结束这次请求的处理过程
解决中文乱码问题
设置响应头
server.on('request', (req, res) => {
res.setHeader('Content-Type', 'text/html;charset=utf-8')
res.end('你好')
})
根据不同的 url 响应不同的 html 内容
const http = require('http')
const server = http.createServer()
server.on('request', (req, res) => {
// 1. 获取请求的 url 地址
const url = req.url
// 2. 设置默认的响应内容为 404 Not found
let content = '<h1>404 Not found!</h1>'
// 3. 判断用户请求的是否为 / 或 /index.html 首页
// 4. 判断用户请求的是否为 /about.html 关于页面
if (url === '/' || url === '/index.html') {
content = '<h1>首页</h1>'
} else if (url === '/about.html') {
content = '<h1>关于页面</h1>'
}
// 5. 设置 Content-Type 响应头,防止中文乱码
res.setHeader('Content-Type', 'text/html; charset=utf-8')
// 6. 使用 res.end() 把内容响应给客户端
res.end(content)
})
server.listen(80, () => {
console.log('server running at http://127.0.0.1')
})
模块化
- 内置模块(内置模块是由 Node.js 官方提供的,例如 fs、path、http 等)
- 自定义模块(用户创建的每个 .js 文件,都是自定义模块)
- 第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)
- 使用 require() 加载自定义模块时,必须指定以./或../开头的路径标识符
模块作用域
和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,外部文件是访问不到的,这种模块级别的访问限制,叫做模块作用域
exports对象
- module.exports 对象可以将模块内的成员共享出去,供外界使用
- 外界用 require() 方法导入自定义模块时,得到的就是 module.exports 所指向的对象
- 导入模块时,导入的结果,永远以module.exports指向的对象为准
const username = 'ifer';
const sum = (a, b) => a + b;
// 最佳实践,推荐写法
module.exports = {
username,
sum
};
/* // 往 module.exports 对象上挂载了一个属性是一个字符串
module.exports.username = username;
// 往 module.exports 对象上挂载了一个属性是一个方法
module.exports.sum = (a, b) => a + b;
CommonJs模块化规范
- 每个模块内部,module 变量代表当前模块
- module 变量是一个对象,它的 exports 属性(即 module.exports)是对外的接口
- 加载某个模块,其实是加载该模块的 module.exports 属性。require() 方法用于加载模块
npm和包
- 装包命令 : npm i 完整的名称
- 初次装包后会多一个 node_modules 的文件夹和 package-lock.json 的配置文件
- node_modules 文件夹用来存放所有已安装到项目中的包(项目开发中要将其添加到 .gitignore 忽略文件中)
- package-lock.json 配置文件用来记录node_modules 目录下的每一个包的下载信息
包管理配置文件
- 项目开发时应当在根目录中创建一个package.json
- 通过 npm init -y 命令创建该配置文件
- 通过 npm i 命令可以一次性安装所有的依赖包
- 通过 npm uninstall 包名 来卸载指定的包
- devDependencies节点(只在项目开发阶段用到)
- 通过 npm i 包名 -D 命令创建
- dependencies(开发和上线都会用到)
Express
专门用来创建Web服务器,基于http模块封装出来的
创建web服务器流程
const express = require('express')//调用express模块
const app = express()//创建web服务器
监听请求
app.listen(80, () => {
console.log('express server running ar http://127.0.0.1')
})
托管静态资源
- express.static() 函数可以对外提供静态资源,将public目录里下的图片,html,css,js等文件对外开发访问
- app.ues(express.static('public'))
- 存放静态文件的目录不会出现在URL中
- 如果希望在托管的静态资源的访问路径中,挂载路径前缀可以通过以下方式
app.use('/public',express.static('public'))
Express路由
- 路由指的是客户端请求与服务器处理函数之间的映射关系
- 路由由三部分组成:请求类型;请求的URL地址;处理函数
app.get('/',(req,res)=>{
})
模块化路由
//router.js文件里的代码
//导入express模块
const express = require('express')
//创建路由对象
const router = express.Router()
//挂载路由
router.get('/', (req, res) => {
console.log()
})
//向外导出路由对象
module.exports = {
router
}
-------------分割线---------------
const express = require('express')
const app = express()
//导入路由模块
const router=express('./router.js')
//注册路由
app.use(router)
为路由模块添加前缀 app.use('/api',router)
中间件
中间件作用:多个中间件之间,共享同一份 req 和 res。 基于这样的特性,我们可以在上游的中间件中,统一为 req 或 res 对象添加自定义的属性或方法,供下游的中间件或路由进行使用。(主要是针对有多个路由同时需要的属性和方法)
全局生效的中间件
连续定义多个全局中间件时,客户端请求到达服务器时,会按照定义的先后顺序进行调用
//定义一个中间件函数
const mw=(req,res,next)=>{
consolo.log('这是个最简单的中间件函数')
next()
}
//全局生效
app.use(mw)
//简便写法
app.use((req,res,next)=>{
consolo.log('这是个最简单的中间件函数')
next()
})
next函数是实现多个中间件连续调用的关键
局部生效的中间件
不使用app.use()定义的中间件,其格式如下
const mw1 = (req,res,next)=>{
consolo.log('这是个最简单的中间件函数')
next()
}
//用如下格式连续调用多个中间件
app.get('/',mw1,mw2,(req,res,next) =>{
res.send()
})
中间件的分类
- 应用级别的中间件
- 路由级别的中间件
- 错误级别的中间件(必须注册在所有路由之后!!)
- express内置的中间件
- express.static
- express.json
- express.urlencoded