node.js | 青训营笔记

79 阅读6分钟

这是我参与「第四届青训营 」笔记创作活动的第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

Express写接口