# Node.js与内置模块 基础知识点复盘

黑马程序员Node.js与内置模块 基础知识点复盘

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加

第一章 初识Node
第二章 fs模版
第三章 path模版
第三章 时钟案例
第四章 http模版
第五章 模块化
第六章 包与npm
第七章 包管理配置文件
第八章 express
第九章 路由
第十章 中间件
第十一章 编写接口
第十二章 跨域
注意:写的过程中没有按章节写,但内容都包含在内


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


目标

提示:这里可以添加本文要记录的大概内容:

学习完html、css3、JavaScript 进阶学习Node.js,你会知道node.js是什么?可以做什么?node.js中JavaScript的组成部分?fs模块读写操作文件?path模块处理路径?http模块写一个基本web服务器?


提示:以下是本篇文章正文内容,下面案例可供参考


一、 初识Node

1.1回顾思考

1.11技术支持:HTML CSS JavaScript
!!
1.13.为什么JavaScrip可以在浏览器中被执行?
因为在浏览器中待执行的js代码可以被浏览器中的JavaScript解析引擎 解析执行
1.14.为什么JavaScript可以操作DOW和BOW ?
因为每个浏览器内置了DOW,BOW,Ajax的API函数,因此JavaScript才可以调用
1.15.V8引擎负责解析执行JavaScript代码 内置API是由运行环境提供的特殊接口,只能在所属的运行环境中被调用
在这里插入图片描述
1.16.使用JavaScript能否做后端开发
借助node.js作为运行环境可以做后端开发

1.2 什么是node.js?

Node.js是一个基于Chrome V8引擎的JavaScript运行环境
浏览器是JavaScript的端运行环境
node.js是JavaScript的端运行环境
node.js 中无法调用BOW,DOW 等浏览器内置API

1.3 Node.js可以做什么?

1.Express框架 构建web应用(http://www.expressjs.com.cn/)
2.Electron框架 构建跨平台的桌面应用(https://electronjs.org/)
3.restify框架 构建API接口项目(http://restify.com/)
4.读写和操作数据库、创建实用的命令行工具辅助前端开发

1.4 怎么学?

JavaScript学习路径:JavaScript语法+浏览器内置API(DOW/BOW)+第三方库(jquery,art-template)
Node.js学习路径:JavaScript语法+node.js内置API(fs/path/http)+第三方API模块(express,mysql)

1.5安装node.js

官网:https://nodejs.org/en 建议下载LTS 版本node.js安装即可(建议安装路径不变,一直点下一步,直到finish)
判断是否成功:
打开终端—输入node -v 如果有版本显示 表明安装成功

1.6 在node.js环境中执行JavaScript代码

1.用记事本写一个js文件
2.打开终端cd进文件所在目录运行js代码

C:\Users\29279>cd C:\node.js基础\day01\code

C:\node.js基础\day01\code>node 1.js
hello  node.js

C:\node.js基础\day01\code>

1.7终端快捷键

键盘上箭头 快速定位上一次执行的命令
tab键 快速补全路径
esc键 清空输入命令
cls键 清空当前终端的所有命令


二、fs文件系统模块

2.1 什么是fs文件系统模块?

fs模块是官方提供用来操作文件的模块
fs.readFile()方法 读取文件内容
fs.writeFile()方法 写入文件内容

使用需要导入fs模块

代码如下(示例):

const fs = require('fs')

2.2 读取和写入文件

2.21使用 fs.readFile()方法

代码如下(示例):

const fs = require('fs')//导入fs模块
//调用fs.readFile()方法读取文件
//参数1:文件路径  
//  ~2:读取文件采用的编码格式 默认utf-8
//  ~3:回调函数 拿到文件读取失败或成功的结果
fs.readFile('./file/file.text','utf-8',function(err,dataStr){
    //打印失败的结果
    //成功,err值为null
    //失败:err的值为  错误对象  datastr的值为undefined
    console.log(err)
    console.log('--------')
    //打印成功的结果
    console.log(dataStr)    
})

2.22判断文件是否读取成功

代码如下(示例):

const fs =require('fs')

fs.readFile('./file/file.text','utf-8',function(err,dataStr){
   if(err){
   return console.log('文件读取失败!'+err.message)
   }
   console.log('文件读取成功!'+dataStr)
})

2.23使用 fs.writeFile()方法

代码如下(示例):

const fs = require('fs')
//调用fs.writeFile()方法,写入文件内容
//参数1:文件存放路径
//~2:要写入的内容
//~3:回调函数
fs.writeFile('./file/file.text','I hade crash on you !',function(err){
    //如果文件写入成功:err的值等于null
    //失败:err的值为一个错误对象
    if(err){
      return  console.log('文件写入失败'+err.message)
    }
    console.log('文件写入成功!')

})

2.24 整理成绩案例

代码如下(示例):

//1.导入fs模块
const fs = require('fs')
//2.调用fs.readFile()读取文件内容
fs.readFile('./file/成绩.text','utf-8',function(err,dataStr){
    //3.判断是否读取成功
    if(err){
     return  console.log('文件读取失败!'+err.message)
    }
   // console.log('文件读取成功'+dataStr)
   

   //4.1 先把成绩的数据,按照空格进行分割
   const arrOld = dataStr.split(' ')
   //console.log(arrOld)
   //4.2 循环分割后的数组,对每一项数据,进行字符串的替换操作
   const arrNew = []
   arrOld.forEach(item =>{
    arrNew.push(item.replace('=',':'))
   })
   //console.log(arrNew)
   //4.3把数组中的每一项,进行合并,得到一个新的字符串  \r\n回车换行
   const newStr = arrNew.join('\r\n')
  // console.log(newStr)

   //将处理完成的成绩数据,调用fs.writeFlie()方法,写入到新文件 成绩-ok.text中
   fs.writeFile('./file/成绩-ok.text',newStr,function(err){
    if(err){
        return console.log('文件写入失败!'+err.message)
    }
    console.log('文件写入成功!\r\n'+newStr)
   })
})

2.3 fs模块-路径动态拼接

2.31 路径动态拼接问题
在使用fs模块操作文件时,如果提供的操作路径是以./或…/开头的相对路径时,很容易出现路径动态拼接错误问题。
原因:代码运行时,会以执行node命令时所处的目录,动态拼接处被操作文件的完整路径

代码如下(示例):

const fs = require('fs')

fs.readFile('./file/file.text','utf-8',function(err,dataStr){
    if(err){
      return  console.log('文件读取失败!'+err.message)
    }
    console.log('文件读取成功!'+dataStr)
})
PS C:\node.js基础\day01\code> cd ../
PS C:\node.js基础\day01> node '.\code\1-05 演示路径错误问题.js'
文件读取失败!ENOENT: no such file or directory, open 'C:\node.js基础\day01\file\file.text'
PS C:\node.js基础\day01> cd ../
PS C:\node.js基础> node '.\day01\code\1-05 演示路径错误问题.js'
文件读取失败!ENOENT: no such file or directory, open 'C:\node.js基础\file\file.text'
PS C:\node.js基础>

2.32 解决路径动态拼接问题:直接提供一个完整的文件(绝对路径)存放路径
缺点:移植性差,不利于维护

代码如下(示例):

const fs = require('fs')
//提供完整路径解决路径动态拼接问题
//缺点:移植性差,不利于维护
fs.readFile('C:\\node.js基础\\day01\\code\\file\\file.text','utf-8',function(err,dataStr){
    if(err){
      return  console.log('文件读取失败!'+err.message)
    }
    console.log('文件读取成功!'+dataStr)
})
PS C:\node.js基础\day01\code> node '.\1-05 演示路径错误问题.js'
文件读取成功!I hade crash on you !
PS C:\node.js基础\day01\code> cd ../
PS C:\node.js基础\day01> node '.\code\1-05 演示路径错误问题.js'
文件读取成功!I hade crash on you !
PS C:\node.js基础\day01> cd ../
PS C:\node.js基础> node '.\day01\code\1-05 演示路径错误问题.js'
文件读取成功!I hade crash on you !
PS C:\node.js基础>

2.33 __dirname 解决动态路径拼接问题解决:缺点移植性差,不利于维护

代码如下(示例):

fs.readFile(__dirname+'/file/file.text','utf-8',function(err,dataStr){
     if(err){
       return  console.log('文件读取失败!'+err.message)
     }
    console.log('文件读取成功!'+dataStr)
 })
PS C:\> node '.\node.js基础\day01\code\1-05 演示路径错误问题.js'
文件读取成功!I hade crash on you !
PS C:\>

建议:以后尽量使用__dirname拼接路径

三、path路径模块

3.1 path基本方法

定义:path模块是Node.js官方提供的,用来处理路径的模块。
3.11 使用前导入模块

const path = require('path')

3.12方法:

path.join()方法 用来将多个路径片段拼接成一个完整的路径字符串

代码如下(示例):

const path = require('path')
const fs = require('fs')
//注意:../会抵消前面的路径
const pathStr = path.join('/a','/b/c','../','./d','e')
console.log(pathStr)
//打印结果  \a\b\d\e


//fs.readFile(__dirname+'/file/file.text')  不推荐使用这种+链接路径

fs.readFile(path.join(__dirname,'/file/file.text'),'utf-8',function(err,dataStr){
    if(err){
        return console.log(err.message)
    }
    console.log(dataStr)
})

注意:今后凡是涉及路径拼接的操作,都要使用path.join ()方法进行处理。不要直接使用+进行字符串的拼接

path.basename()方法 用来从路径字符串中,将文件名解析出来

代码如下(示例):

const path = require('path')
const fs = require('fs')

const fpath = 'a/b/c/index.html'

var fullName = path.basename(fpath)
console.log(fullName) //输出index.html


var nameWithoutExt = path.basename(fpath,'.html')
console.log(nameWithoutExt)//输出 index

path.extname()获取文件扩展名

代码如下(示例):

const path = require('path')

const fpath = 'a/b/c/index.html'//路径字符串


const fext = path.extname(fpath)
console.log(fext)//输出  .html

3.2 综合案例 - 时钟案例

3.21实现步骤
1.创建两个正则表达式,分别用来匹配页面中style和script标签
2.使用fs模块,读取需要处理的HTML文件
3.自定义resolveCSS方法,来写入index.css样式文件
4.自定义resolveJs方法,来写入index.js脚本文件
5.自定义resolveHTML方法,来写入index.html脚本文件

代码如下(示例):

//1.1导入fs、path模块
const fs = require('fs')
const path =  require('path')
//1.2定义正则表达式,分别匹配<style></style>和<script></script>标签
const regStyle = /<style>[\s\S]*<\/style>/
const regScript = /<script>[\s\S]*<\/script>/


//2.1使用fs.readFile()方法读取文件
fs.readFile(path.join(__dirname,'./clock/index.html'),'utf-8',function(err,dataStr){
     //读取文件失败
    if(err) return console.log('读取文件失败!'+err.message) 
    //读取文件成功后,调用对应三个方法,分别解析出css,js,html文件
    resolveCss(dataStr)
    resolveJS(dataStr)
    resolveHTML(dataStr)
})


//3.1定义处理css样式的方法
function resolveCss(htmlStr){
    //3.2使用正则提取需要的内容
    const r1 = regStyle.exec(htmlStr)
    //3.3将提取出来的样式字符串,进行字符串的replace替换操作
    const newCSS = r1[0].replace('<style>','').replace('</style>','')
    
    fs.writeFile(path.join(__dirname,'./clock/index.css'),newCSS,function(err){
        if(err)return console.log('写入css样式失败!'+err.message)
        console.log('写入样式文件成功!')
    })
}


//4.1定义处理js脚本的方法
function resolveJS(htmlStr){
    //4.2通过正则,提取对应的<script></script>标签内容
    const r2 = regScript.exec(htmlStr)
    //4.3将提取出来的样式字符串,进行字符串的replace替换操作
    const newJS = r2[0].replace('<script>','').replace('</script>','')
    //4.4将处理的结果,写入到clock目录中的index.js文件里面
    fs.writeFile(path.join(__dirname,'./clock/index.js'),newJS ,function(err){
        if(err) return console.log('写入JavaScript脚本失败!'+err.message)
        console.log('写入JS脚本成功!')
    })
}


//5.1定义处理html的方法
function resolveHTML(htmlStr){
    //5.2将字符串调用replace方法,把内嵌的style和script标签,替换为link和script标签
    const newHTML = htmlStr.replace(regStyle,"<link rel='StyleSheet' href='./clock/index.css'/>").replace(regScript,"<script src='./clock/index.js'></script>")
    //5.3写入index.html这个文件
    fs.writeFile(path.join(__dirname,'./clock/index.html'),newHTML,function(err){
        if(err) return console.log('写入HTML文件失败!'+err.message)
        console.log('写入HTML页面成功!')
    })
}

注意 fs.writeFile()方法只能用来创建文件,不能用来创建路径 重复调用fs.writeFile()写入同一个文件,新写入的内容会覆盖之前的旧内容

四、http模块

4.1 什么是http模块

4.11定义
http模块是Node.js官方提供的、用来创建web服务器的模块,通过http模块提供的http.createServer()方法,就能方便的把一台普通的电脑,变成一台web服务器,从而对外提供web资源服务

4.12导入模块

代码如下(示例):

const http = require('http')

4.2 创建最基本的web服务器

4.21创建最基本的web服务器基本步骤
1.导入http模块
2.创建web服务器实例
3.为服务器实例绑定request事件,监听客户端请求
4.启动服务器

代码如下(示例):

//导入http模块
const http = require('http')

//创建web服务器实例
const server = http.createServer() 

//为web服务器实例绑定requet事件,监听客户端请求
server.on('request',(req,res)=>{
    console.log('Welcome to my Webserver!')
})

//启动服务器
server.listen(80,() =>{
    console.log('http server running at http://127.0.0.1')
})

4.22 req请求对象、 res响应对象

代码如下(示例):

const http = require('http')


const server = http.createServer()


server.on('request',(req,res)=>{
    //req.url是客户端请求的URL地址
    const url = req.url
    //req.method 是客户端请求的method的类型
    const method = req.method
    const str = `You request url is ${url},and request method is ${method}` //注意为反单引号,不是单引号
    //req 请求对象
   console.log(str)
     //调用 res.setHeader()方法,设置Content-Type响应头,解决中文乱码的问题
   res.setHeader('Content-type','text/html;charset=utf-8')
 //res.end的作用“向客户端发送指定的内容,并结束这次请求的过程”
     res.end(str)
})

server.listen(80,()=>{
    console.log('server running at http://127.0.0.1')
})

4.23解决中文乱码问题
当调用res.end()方法,向客户端发送中文内容的时候,会出现乱码问题,此时需手动设置内容的编码格式,设置Content-Type响应头,解决中文乱码的问题。

4.3根据不同的url响应不同的html内容

1.获取请求的url地址
2.设置默认的响应内容为404 Not found
3.判断用户请求的是否为/或/index.html
4.判断用户请求的是否为about.html关于页面
5.设置Content-Type响应头,防止中文乱码
6.使用res.end()把内容响应给客户端

代码如下(示例):

const http = require('http')

const server = http.createServer()

server.on('request',function(req,res){
    const  url = req.url                    //1.获取请求的url地址
                                            //2.1let和const的区别:let是创建新变量,const则是引用已经存在的
    let Content = '<h1>404 Not found</h1>'   //2.2设置默认的内容为404  Not found
    //  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(8081,()=>{
    console.log('server running at http://127.0.0.1:8081')
})

4.4案例 - 实现clock时钟的web服务器

4.41实现步骤:
1.导入需要的模块
2.创建基本的web服务器
3.将资源的请求url地址映射为文件的存放路径
4.读取文件内容并响应给客户端
5.优化资源的请求路径

代码如下(示例):

//1.导入需要的模块
const fs = require('fs')
const path = require('path')
const http = require('http')
//2.创建基本的web服务器
const server = http.createServer()


server.on('request',(req,res)=>{
//3.将资源的请求url地址映射为文件的存放路径
const url = req.url
//const fpath = path.join(__dirname,url)
//5.优化资源的请求路径
//5.1预定义空白文件存放路径
let fpath = ''
if(url==='/'){
    //5.2如果请求的路径为/,这需要手动指定文件存放路径
    fpath = path.join(__dirname,'/day02/code/clock/index.html')
}else{
    //5.3如果请求的路径不为/ 则动态拼接文件路径
    fpath = path.join(__dirname,'./day02/code/clock',url)
}

// /day02/code/clock/index.html  相对路径



//4.读取文件内容并响应给客户端
//4.1根据"映射"过来的文件路径读取文件的内容
 fs.readFile(fpath,'utf-8',(err,dataStr)=>{
    //4.2读取失败,向客户端响应固定的'错误消息'
    if(err) return res.end('404 Not found!')
    //4.3读取成功,将读取成功的内容,响应给客户端
    res.end(dataStr)
 })
})

server.listen(8086,()=>{
    console.log('server running at http://127.0.0.1:8086')
})

五、模块化

5.1 模块化的基本概念

5.11什么是模块化
模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程,对于整个系统来说,模块是可组合、分解和更换的单元(就是大文件拆分成独立且相互依赖的多个小模块)
优点:
复用性
可维护性
按需加载

5.12模块化规范
使用规定语法格式引用模块/暴露成员

5.2 Node.js中模块化

5.21Node.js 中模块分类
内置模块:官方提供 fs path http 等模块
自定义模块:用户创建 的.js文件
第三方模块:第三方开发 使用需下载
5.22 加载模块
使用requrie()方法加载三种模块 语法格式稍有不同

代码如下(示例):

// 1.加载内置的fs模块
const fs =require('fs')

//2.加载用户自定义模块
const Custom = require('./Custom.js')//可以省略.js后缀名

//3.加载第三方模块 需下载使用
const moment = require('moment')

注意:使用require()方法加载其他模块时,会执行被加载模块中的代码

5.23Node.js中模块作用域
1.什么是模块作用域
和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内访问,无法在外界被访问。
优点:防止全局变量污染

代码如下(示例):

//---------2-07模块作用域.js文件
const username = '张珊'

function sayHello(){
    console.log('大家好,我是'+username)
}
//-----------1-07 test.js 文件
const Custom = require('./2-07模块作用域')
console.log(Custom)//打印结果为{}

5.24向外共享模块作用域中的成员
5.241module对象
每个.js自定义模块中都有一个module对象 存储当前模块有关信息
test:

console.log(module)

5.241module.exports 对象
可以使用 module.exports对象将模块内成员共享出去 供外界(得到 module.exports 所指向的对象)使用

代码如下(示例):

//---------2-11自定义模块.js文件
//module.exports 对象挂载username属性
module.exports.username = 'sa'
//module.exports 对象挂载sayHello方法
module.exports.sayHello = function(){
    console.log('hello!')
}
const sa = '19'
module.exports.sa =sa

//让module.exports指向一个全新的对象
module.exports = {
    nickname:'小金',
    sayHi(){
        console.log('Hi!')
    }
}
//---------2-12test.js文件
const m = require('./2-11自定义模块')
console.log(m)//{打印结果:module.exports指向一个全新的对象 nickname: '小金', sayHi: [Function: sayHi] }

注意:永远以module.exports指向的对象为准

5.242 exports 对象
exports 对象目的为简化代码 。默认情况下,exports和module.exports指向同一个对象,最终共享结果以module.exports指向的对象为准
test;

onsole.log(exports)
console.log(module.exports)

console.log(exports===module.exports)//打印结果为true

exports基础使用示例

代码如下(示例):

//---------2-13exports对象.js文件
const username = '小骨'
exports.username = username
exports.age = 20
exports.sayHello = function(){
    console.log('大家好!')
}
//---------2-14test.js文件
const m = require('./2-13exports对象.js')
console.log(m)

5.25exports和module.exports的使用误区

在这里插入图片描述

画图理解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

六、 npm与包

5.31包
来源:第三方个人或团队开发出来,免费开源供所有人使用
与内置模块的关系:包是基于内置模块封装出来的 提高效率
5.32下载包
国外一架IT公司 npm,Inc 旗下网站 http://www.npmjs.com/ 全球最大包共享平台
该公司还提供了一个地址为https://registry.npmjs.org/的服务器,对外共享所有包,可以通过这个服务器下载自己所需的包

注意
1.从 http://www.npmjs.com/网站上搜索自己需要的包
2.从https://registry.npmjs.org/服务器下载自己需要的包

在这里插入图片描述

5.33npm初体验

1.格式化时间的传统做法:

创建格式化时间的自定义模块:

//定义格式化时间的方法
function dateFormate(dtStr){
    const dt = new Date(dtStr)


    const y = dt.getFullYear()
    const m = padZero(dt.getMonth())
    const d = padZero(dt.getDate())

    const hh = padZero(dt.getHours())
    const mm = padZero(dt.getMinutes())
    const ss = padZero(dt.getSeconds())
    
    return `${y}-${m}-${d}  ${hh}:${mm}:${ss}`
}

//定义补零函数
function padZero(n){
    return n>9?n:"0"+n
}

module.exports={
    dateFormate
}

调用格式化时间的自定义模块:

//导入自定义的格式化时间的模块
const TIME = require('./3-01dateFormate')


//调用方法:进行时间的格式化
const dt =new Date()
// console.log(dt) 打印没有格式化时间  进行对比
const newDT = TIME.dateFormate(dt)
console.log(newDT)

2.格式化时间的高级做法:

在项目中安装包的命令

npm install 包完整的名称
//简写
npm i 包完整的名称

终端安装格式化时间需要的包

npm i moment

注意:包的使用可以到npmjs.com官网查看相关用法

代码如下(示例):

//1.导入需要的包
//注意:导入的名称,就是装包的名称
const moment = require('moment')

const newDt = moment().format("YYYY-MM-DD HH:mm:ss")
console.log(newDt )

5.34初次安装包后的注意事项
(1)文件:
会多一个node_modules文件夹和package-lock.json的配置文件

node_modules文件夹:存放所有已经安装到项目中的包,require()导入第三方包,就是从这个目录中查找并加载包。

package-lock.json配置文件:用来记录包的下载信息 名字、版本号、下载地址、开发期间用到、开发和部署用到等。
(包管理配置文件必须在项目根目录中)

(2)安装指定版本的包:

npm i moment@2.22.2

(3)包的语义版本规范:
版本号是以点分十进制 定义: 2.24.0
1:大版本
2:功能版本
3:Bug修复版本

:版本号提升的规则:只要前面的版本号增长了,后面的版本号归零。

(4)注意团队成员中共享项目的源代码时,剔除node_modules目录后,创建package.json配置文件记录安装了那些包,以方便减少内存。

(5)快速创建package.json

作用:在执行命令所处的目录中,快速创建package.json文件

npm init -y

注意:1.上述命令只能在英文的目录下成功运行,所以项目文件夹的名称一定要使用英文命名,不使用中文和空格 2.运行npm install命令安装包的时候,npm包管理工具会自动把包的名称和版本号,记录到package.json文件中。

(6)dependencies节点
package.json文件中有一个dependencies节点,专门用来记录您使用npm install命令安装了那些包
(7)一次性安装所有的包
执行npm install 命令时,npm包管理工具会先读取package.json中的dependencies节点中的依赖包名称和版本号后会一次性下载所有的包。

npm install

(8)卸载包
无简写模式

npm uninstall moment

(6) devDependencies节点
如果某些包只在项目开发阶段会用到,在项目上线之后不会用到,建议放到devDependencies节点中
与之,开发阶段会用到,在项目上线之后也会用到,建议放到dependencies节点中。

npm i 包名 -D
//完整写法:
npm install 包名 --save-dev

代码如下(示例):

npm install webpack -D

5.35解决下包速度慢的问题
1,为什么慢?
下包默认从国外的https://registry.npmjs.org/服务器进行下载,网络数据传输需要经过漫长的海底光缆,因此慢。
2,解决下包速度慢的问题:
淘宝NPM镜像服务器:专门隔一段时间同步国外官方服务器的包到国内的服务器
镜像:一种文件存储形式,一个磁盘上数据在另一个磁盘存在完全相同的副本即为镜像
3,切换npm的下包镜像源

//查看当前的下包镜像源
npm config get registry
//将下包的镜像源切换为淘宝镜像源
npm config set registry=https://registry.npm.taobao.org/

4,nrm
为了更方便的切换下包的镜像源,安装nrm小工具,可以快速查看和切换下包的镜像源

代码如下(示例):

//通过npm包管理器,将nrm安装为全局可用的工具
npm i nrm -g
//查看所有可用的镜像源
nrm ls
//将下包的镜像源切换为taobao镜像
nrm use taobao

5.36项目包
项目包:被安装到项目的node_modules目录中的包,都是项目包

分类:
开发依赖包:(被记录到devDependencies节点中,只会在开发期间会用到)
核心依赖包:(被记录到dependencies节点中,在开发期间和项目上线之后都会用到)

npm i 包名 -D (被记录到devDependencies节点中)
npm i 包名 (被记录到dependencies节点中)

全局包:执行npm install命令时,如果提供了-g参数,则会把包安装为全局包
全局包安装目录:C:\Users\用户目录\AppData\Roaming\npm\node_modules 目录下

npm i 包名 -g   //全局安装指定的包
npm uninstall 包名 -g // 卸载全局安装的包

只有工具性质的包,才有全局安装的必要性,因为提供好用的终端命令。参考官方提供的使用说明
5.36包的分类
i5ting_toc是一个可以把md文档转为html页面的小工具

//将i5ting_toc安装为全局包
npm install -g i5ting_toc
//调用i5ting_toc,轻松实现md转html的功能
i5ting_toc -f 要转换的md文件路径 -o

5.37规范的包结构
包的内部结构
三点要求:
1.包必须以单独目录存在
2.包的顶级目录下要必须包含package.json这个包管理配置文件
3.package.json中必须包含name,version,main三个属性,分别代表包的名字、版本号,包的入口。
注意:以上三点是基本约束,更多参考 https://yarnpkg.com/zh-Hans/docs/package-json网站

5.38如何开发一个属于自己的包
1.格式化日期
2.转义HTML中的特殊字符
3.还原HTML中的特殊字符
在这里插入图片描述
2.初始化包的基本结构
1.新建itheima-tools文件夹,作为包的根目录
2.在itheima-tools文件夹中,新建如下三个文件:
package.json(包管理配置文件):

代码如下(示例):

{
    "name": "itheima-tools",
    "version": "1.0.0",
    "main": "index.js",
    "description": "提供了格式化时间、HTML.Escape相关的功能",
    "keywords": [
        "itheima",
        "dateFormat",
        "escape"
    ],
    "license":"ISC"
}

index.js(包的入口文件):

//这是包的入口文件
const date = require('./dateFormat')
const escape = require('./htmlEscape')

//向外暴露需要的
module.exports={
    //...向外展开
  ...date,
  ...escape

}

README.md(包的说明文档):

代码如下(示例):

##安装

npm install itheima-tools


##导入
```js
const itheima = require('itheima-tools')

##格式化时间

//调用dataformate 对时间进行格式化
const newdt = TIME.dateFormate(new Date())
//结果  2024-03-20  20:51:00
console.log(newdt)

##转义html中的特殊字符

//待转化的html字符
const htmlStr = '<h1 title="abc">这是h1标签<span>123&nbsp</span></h1>'
//调用htmlEscape方法进行转换
const str = TIME.htmlEscape(htmlStr)
//转换结果   &lt;h1 title=&quot;abc&quot;&gt;这是h1标签&lt;span&gt;123&amp;nbsp&lt;/span&gt;&lt;/h1&gt;
console.log(str)

##还原html中的特殊字符

//待还原的html字符串
const str2 = TIME.htmlUnEscape(str)
//输出结果   <h1 title="abc">这是h1标签<span>123&nbsp</span></h1>
console.log(str2)

##开源协议
ISC


`vscode中ctrl+f 快捷键:查找文件中的某个代码`
关于license许可协议相关的内容,可参考[更多license许可协议相关的内容](https://www.jianshu.com/p/86251523e898)

3.定义转义html的方法

```javascript
//../itheima-tools/index.js文件

//定义转义html的方法
function htmlEscape(htmlStr){
    return htmlStr.replace(/<|>|"|&/g,(match)=>{
        switch(match){
            case '<':
                return '&lt;'
            case '>':
                return '&gt;'
            case '"':
                return '&quot;'
            case '&':
                return '&amp;'
        }
    })
    
}


//定义还原html的方法
function htmlUnEscape(str){
    return str.replace(/&lt;|&gt;|&quot;|&amp;/g,(match)=>{
        switch(match){
            case '&lt;':
                return'<'
            case '&gt;':
                return'>'   
            case '&quot;':
                return'"'
            case '&amp;':
                return'&'
        }
    })
}
//向外暴露需要的
module.exports={
    htmlEscape,
    htmlUnEscape
}
const TIME = require('../itheima-tools/index')
const htmlStr = '<h1 title="abc">这是h1标签<span>123&nbsp</span></h1>'
const str = TIME.htmlEscape(htmlStr)
//测试还原html的方法
const str2 = TIME.htmlUnEscape(str)
console.log(str2)

在这里插入图片描述

在这里插入图片描述

5.38发布包
1.注册npm账号
(1)访问npm网站点击sign up 按钮,进入注册用户界面
(2)填写账号相关的信息:FullName、Public Email、 Username、Password
(3)点击Create an Account按钮,注册账号
(4)点击邮箱验证链接
2.登录npm账号
终端执行:npm login 命令

npm login

执行前要把下包的服务器切换到npm的官方服务器执行前要把下包的服务器切换到npm的官方服务器
终端登录成功后cd进包目录执行npm publish命令

PS C:\node.js基础\itheima-tools-sliverlin> npm publish

5.39删除已发布的包
运行npm unpublish 包名 --force命令 ,既可以从npm删除已发布的包
注意:npm unpublish命令只能删除72小时以内发布的包,超过72小时永远不能删除 npm unpublish命令删除的包,在24小时内不允许重复发布

npm unpublish itheima-tools-sliverlin  --force

尽量不要在npm发布没有意义的包

5.4 模块的加载机制

5.41优先从缓存中加载

模块在第一次加载后会被缓存,这也意味着多次调用require()不会导致模块的代码被执行多次,无论什么模块都是从缓存中加载,提高模块的加载效率

5.42内置模块的加载机制

内置模块是由Node.js官方提供的模块,内置模块的加载优先级最高
即使与内置模块fs名字与包fs名字相同,require(‘fs’)返回的依旧是内置的fs模块

5.43自定义模块的加载机制

使用reuire()加载自定义模块时,必须指定以./或…/开头的路径标识符,如果没有node会把它当作内置模块或第三方模块进行加载。
使用require()导入自定义模块时,如果省略文件的扩展名 ,node.js会按顺序尝试加载以下文件:
1.确切文件名加载
2.补全.js扩展名加载
3.补全.json扩展名加载
4.补全.node扩展名加载
5.加载失败终端报错

5.44第三方模块的加载机制

在这里插入图片描述

5.45目录作为模块

把目录作为模块标记符,传递给require()进行加载的时候,有三种加载方式
1.在被加载的目录下查找一个叫做package.json的文件,并寻找main属性,作为require()加载的入口
2.目录如果没有package.json文件,或者mian.js入口不存在或无法解析,会加载目录下index.js文件
3.以上两步都失败了,Node.js会在终端打印错误信息

七、express

5.51.初识Express

1.简介:
Express是基于Node.js平台,快速、开放、极简的Web开发框架
通俗理解:作用和Node.js内置的http模块类似,专门用来创建web服务器的
本质:是一个npm上的第三方包,提供了快速创建web服务器的便捷方法
Express的中文官网

思考:
1.有了http模块为什么还要express?
http内置模块复杂,开发效率低,express是基于http模块进一步封装出来的,能够极大的提高开发效率。
2.http内置模块与express什么关系
类似于浏览器Web API 和jQuery的关系,后者是基于前者进一步封装出来的。
3.express能做什么
前端程序员必备常见两种服务器
web网站服务器:专门对外提供web网页资源的服务器
API接口服务器:专门对外提供API接口的服务器
使用Express,可以快速创建web网站服务器和API接口服务器。

2.安装

npm i express@4.17.1

postman安装: postman网址

3.express的基本使用

代码如下(示例):

//1.导入express
const express = require('express')

//2.创建web服务器
const app = express()
//4.使用app.get()方法、app.post()方法 监听客户端的GET POST请求,并向客户端响应具体的内容
app.get('/user',(req,res)=>{
    //调用express提供的res.send()方法,向客户端响应一个  JSON对象
    res.send({name:'安家乐',gender:'男',age:23})
})


app.post('/user',(req,res)=>{
    //调用express提供的res.send()方法,向客户端响应一个  文本字符串
   res.send("请求成功!")
})

//3.调用app.listen(端口好,启动成功后的回调函数),启动服务器
app.listen(80,()=>{
    console.log('express server running at http://127.0.0.1')
})

(1)获取URL中携带的查询参数
通过req.query对象,可以访问到客户端通过查询字符串的形式,发送服务器的参数

//其余代码省略
app.get('/',(req,res)=>{
    //通过req.query可以获取到客户端发送过来的 查询参数
    //注意:默认情况下,req.query是一个空对象。
    console.log(req.query)
    res.send(req.query)
})

postman中:http://127.0.0.1/?name=宝宝&age=20 (直接在url写参数与到方法内写是一样的,都打印出对象{ name: ‘宝宝’, age: ‘20’ })

(2)获取URL中的动态参数
通过req.params对象,可以访问到URL中,通过匹配的动态参数

app.get('/user/:id',(req,res)=>{
    //通过req.params对象  可以动态匹配参数值  默认是一个空对象
    console.log(req.params)
    res.send(req.params)
})

注意:冒号后面的id参数可以任意起合法名字,且可跟多个参数

5.52express.static()快速托管静态资源

1.express.static()托管静态资源

express.static()可以创建一个静态资源服务器

const express = require('express')

const app = express()
//调用express。static()方法,快速对外提供静态资源
app.use(express.static('./clock'))
app.listen(80,()=>{
    console.log('express server running at http://127.0.0.1')
})

注意:Express在指定的静态目录中查找文件,并对外提供资源访问路径,因此,存放静态文件的目录名不会出现在URL中
2.express.static()托管多个静态资源

//那个文件在前,就先托管那个文件
app.use(express.static('./files'))
app.use(express.static('./clock'))

3.挂载路径前缀

app.use('/public',express.static('/public'))
//访问files文件中的文件必须加上/files
app.use('/files',express.static('./files'))

4.nodemon工具
nodemon工具作用监听项目文件变动,当代码被修改后,nodemon会自动帮助我们重启项目,方便开发和调试
网站:nodemon工具
(1)安装nodemon

npm i -g nodemon

(2)使用nodemon

nodemon ‘文件名’

注意:vscode报错,nodemon 在此系统上禁止运行脚本,解决办法如下:

1.vscode报错,nodemon :因为在此系统上禁止运行脚本

注意:不仅仅适用于nodemon报错,报在此系统上禁止运行脚本的错都可以用以下方法解决

2.报错原因分析:windows 为了安全,默认的执行策略为 Restricted,因此需要将执行策略设置为 RemoteSigned 即可

3.解决方法

(1) get-executionpolicy

 如果你电脑显示是RomoteSigned,那就不用改了

如果不是,往下看 

(2)修改执行策略为RemoteSigned

  set-ExecutionPolicy RemoteSigned

(3)get-executionpolicy  返回 RemoteSigned  验证修改成功。

修改执行策略风险须知:
在这里插入图片描述

5.53express路由精简项目结构

1.路由:
路由是按键与服务之间的映射关系
Express路由:路由指的是客户端的请求与服务器处理函数之间的映射关系
三部分构成:请求的类型、请求的URL地址、处理函数

在这里插入图片描述
2.路由的用法
初始化包管理配置文件:

npm init -y

(1)模块化路由
可以直接在app上挂载路由,此举不建议 推荐将路由抽离为单独的模块。
1.创建路由模块对应的.js文件
2.调用express.Router()函数创建路由对象
3.向路由对象上挂载具体的路由
4.使用module.exports向外共享路由对象
5.使用app.use()函数注册路由模块

代码如下(示例):服务器

const express = require('express')
const app = express()

//1.导入路由模块
const router =require('./router')
//2.注册路由模块
//用于其他:app.use(express.static('./files'))
app.use(router)

//注意:app.use()函数的作用,就是来注册全局中间件

app.listen(80,()=>{
    console.log('express server running at http://127.0.0.1')
})

代码如下(示例):路由模块

//路由模块
//1.导入express
const express = require('express')
//2.创建路由对象
const router = express.Router()


//3.挂载具体路由
router.get('/user/list',(req,res)=>{
    res.send('Get user list')
})

router.post('/user/add',(req,res)=>{
    res.send('Add new user')
})

//4.向外导出路由对像
module.exports = router

(2)为路由模块添加前缀

app.use('/api',router)

访问地址:http://127.0.0.1/api/user/list

5.54express中间件

1.中间件概念:
例子:污水处理环节就是中间件
2.中间件的格式
express中间件本质就是一个function处理函数
中间件的处理函数必须包含next参数,而路由处理函数中只包含req,res
3.next函数的作用
next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或者路由。

代码如下(示例):定义一个简单的中间件函数

const express = require('express')
const app = express()
//定义一个最简单的中间件函数
const mw = function(req,res,next){
    console.log('这是最简单的中间件函数')
    //把流转关系,转交给下一个中间件或路由
    next()
}
app.listen(80,()=>{
    console.log('http://127.0.0.1')
})

4.全局生效的中间件
调用app.use(中间件函数)即可定义一个全局生效的中间件。

代码如下(示例):全局生效的中间件

const express = require('express')
const app = express()
//定义一个最简单的中间件函数
const mw = function(req,res,next){
    console.log('这是最简单的中间件函数')
    //把流转关系,转交给下一个中间件或路由
    next()
}
//将mv注册为全局生效的中间件
app.use(mw)

app.get('/',(req,res)=>{
    res.send('Home page.')
})

app.post('/user',(req,res)=>{
    res.send('User page.')
})

app.listen(80,()=>{
    console.log('http://127.0.0.1')
})

5.中间件的作用
多个中间件之间,共享一份req和res,基于这样的特性,我们可以在上游的中间件中,统一为req或res对象添加自定义的属性和方法,供下游的中间件或路由进行使用。

全局生效的中间件简化形式:

app.use((req,res,next)=>{
    console.log('这是最简单的中间件函数')
    next()
})

代码如下(示例):中间件的作用

const express = require('express')
const app = express()

app.use((req,res,next)=>{
    //获取到请求到达服务器的时间
    const time = Date.now()
    //为req对象,挂载自定义属性,从而把时间共享给后面的所有路由
    req.startTime = time
    next()
})

app.get('/',(req,res)=>{
    res.send('Home page.'+ req.startTime)
})

app.post('/user',(req,res)=>{
    res.send('User page.'+ req.startTime)
})

app.listen(80,()=>{
    console.log('http://127.0.0.1')
})

6.定义多个全局中间件
可以使用app.use()连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行性。

代码如下(示例):定义多个全局中间件

const express = require('express')
const app =express()
//定义第一个全局中间件
app.use((req,res,text)=>{
    console.log('这是第一个全局中间件')
    text()
})

//定义第一个全局中间件
app.use((req,res,text)=>{
    console.log('这是第二个全局中间件')
    text()
})

//定义路由
app.get('/user',(req,res)=>{
    res.send("这是路由")
})

app.listen(80,()=>{
    console.log('http://127.0.0.1')
})

7.局部生效的中间件
不使用app.use()定义的中间件,叫做局部生效的中间件

代码如下(示例):局部生效的中间件

const express = require('express')

const app = express()

//创建局部中间件
const net = (req,res,text)=>{
    console.log('调用了局部生效的中间件')
    text()
}
//创建路由
//有三个参数,url 局部中间件  回调函数
app.get('/',net,(req,res)=>{
    res.send('Home page.')
})
app.post('/user',(req,res)=>{
    res.send('User page.')
})

app.listen(80,()=>{
    console.log('express server running at http://127.0.0.1')
})

8.定义多个局部生效的中间件

app.get('/',nw1,nw2,(req,res)=>{
    res.send('Home page.')
})
//或者[]
app.get('/',[nw1,nw2],(req,res)=>{
    res.send('Home page.')
})

注意:1.一定要在路由之前注册中间件 、2.不能忘记调用next()函数 、 3.调用next()函数后不要再写额外代码 、4.连续调用多个中间件时共享req和res对象

9.中间件的分类
(1)应用级别的中间件
通过app.use()或app.get()或app.post(),绑定到app实例上的中间件。
(2)路由级别的中间件
绑定到express.Router()实例上的中间件,应用级别中间件绑定到app实例上,路由级别中间件绑定到router实例上
(3)错误级别的中间件
必须含有四个形参,(err,req,res,next) 作用:专门用来捕获项目发生的异常错误。

代码如下(示例):错误级别的中间件

const express = require('express')

const app = express()
//1.创建路由
app.get('/',(req,res)=>{
    //人为制造错误
    throw new Error('服务器内部发生了错误!')
    res.send('Home page.')
})
//2.定义错误级别的中间件,捕获整个项目的异常错误,从而防止程序的崩溃
app.use((err,req,res,next)=>{
    console.log('发生了错误!'+err.message)
    res.send('Error:'+err.message)
    next()
})


app.listen(80,()=>{
    console.log('express server running at http://127.0.0.1')
})

注意:错误级别的中间件必须注册在所有路由之后!
(4)express内置的中间件
自Express 4.16.0版本开始,Express内置了3个常用的中间件,极大的提高了Express项目的开发效率和体验
1.express.static快速托管静态资源 例如 html文件,图片,css样式等(无兼容性)
2.express.json解析JSON格式的请求数据(有兼容性,仅在4.16.0+版本中可用)
3.express.urlencoded解析URL-encoded格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)
在这里插入图片描述

(5)第三方的中间件
非官方提供,第三方开发 按需下载并配置
例如:在express@4.16.0之前的版本中,经常使用body-parser这个第三方中间件,来解析请求数据,使用步骤:
1.运行npm i body-parser安装中间件
2.使用require导入中间件
3.调用app.use()注册并使用中间件

//1.导入express
const express = require('express')

//2.创建web服务器
const app = express()
//(1)导入解析表单数据的中间件body-parser
const parser = require('body-parser')
//(2)使用body-parser注册中间件
app.use(parser.urlencoded({extended:false}))
//内置中间件:(express.urlencoded({extended:false})
app.post('/user',(req,res)=>{
    console.log(req.body)
    res.send('ok')
})
//3.调用app.listen(端口好,启动成功后的回调函数),启动服务器
app.listen(80,()=>{
    console.log('express server running at http://127.0.0.1')
})

注意:Express内置的express.urlencoded中间件,就是基于body-parser这个第三方中间件进一步封装出来的。

(6)自定义中间件
手动模拟一个类似于express.urlencoded这样的中间件,来解析post提交到服务器的表单数据
步骤:
1.定义中间件
2.监听req的data事件

app.use((req,res,next)=>{
    //定义中间件具体的业务逻辑
    //1.定义一个str字符串,专门用来存储客户端发送过来的请求体数据
    let str = ''
    //2.监听req的data事件
    req.on('data',(chunk)=>{
        str += chunk
    })
})

3.监听req的end事件

app.use((req,res,next)=>{
    //定义中间件具体的业务逻辑
    //1.定义一个str字符串,专门用来存储客户端发送过来的请求体数据
    let str = ''
    //3.监听req的end事件
    req.on('end',()=>{
        //在str中存放的是完整的请求体数据
        console.log(str)
        //TODO:把字符串格式的请求体数据,利用querystring模块中的parse函数解析成对象格式
        const body = qs.parse(str)
        // console.log(body)
        req.body = body
        next()
    })
})

4.使用querystring模块解析请求体数据内置模块querystring模块,专门用来处理查询字符串
在这里插入图片描述
5.将解析出来的数据对象挂载为req.body

app.post('/user',(req,res)=>{
    res.send(req.body)
})

6.将自定义中间件封装为模块

//1.导入querystring模块
const qs = require('querystring')
const bodyParser = (req,res,next)=>{
    //定义中间件具体的业务逻辑
    //1.定义一个str字符串,专门用来存储客户端发送过来的请求体数据
    let str = ''
    //2.监听req的data事件
    req.on('data',(chunk)=>{
        str += chunk
    })
      //3.监听req的end事件
        req.on('end',()=>{
            //在str中存放的是完整的请求体数据
            console.log(str)
            //TODO:把字符串格式的请求体数据,利用querystring模块中的parse函数解析成对象格式
            const body = qs.parse(str)
            // console.log(body)
            req.body = body
            next()
        })
    }
   module.exports = bodyParser 
5.55express创建API接口

1.编写GET接口

router.get('/get',(req,res)=>{
    //通过req.query获取客户端通过查询字符串,发送到服务器的数据
    const query = req.query
    //调用res.send()方法。向客户端响应处理的结果
    res.send({
        status:0,//0表示处理成功,1表示处理失败
        msg:'GET 请求成功!',//状态的描述
        data:query//需要响应给客户端的数据
    })
})

2.编写POST接口

router.post('/post',(req,res)=>{
    //1.获取客户端通过请求体,发送服务器的URL-encoded数据
    const body =req.body
    //2.调用res.send()方法,把数据响应给客户端
    res.send({
        staus:0,//0表示处理成功,1表示处理失败
        msg:'POST请求成功!',//状态的描述
        data:body//需要响应给客户端的数据
    
    })

})

//接口js
//配置解析表单数据的中间件
app.use(express.urlencoded({extended:false}))

注意:如果要去获取URL-encoded格式的请求体数据,必须配置中间件app.use(express.urlencoded({extended:false}))

5.55express中启用cors跨域资源共享

1.接口的跨域问题
刚才编写的GET和POST 接口,存在一个很严重的问题:不支持跨域请求

网站:staticfile.org 由此网站复制juery代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
    <button id="btnGET">GET</button>
    <button id="btnPOST">POST</button>


    <script>
     $(function(){
        //1.测试GET接口
        $('#btnGET').on('click',function(){
            $.ajax({
                type:'GET',
                url:'http://127.0.0.1/api/get',
                data:{name:'zs',age:30},
                success:function(res){
                    console.log(res)
                }
            })
        })
        //2.测试POST接口
        $('#btnPOST').on('click',function(){
            $.ajax({
                type:'POST',
                url:'http://127.0.0.1/api/post',
                data:{name:'水浒传',author:'施耐庵'},
                success:function(res){
                    console.log(res)
                }
            })
        })
        })
       
    </script>
</body>
</html>

2.解决接口跨域问题的方案主要有两种:
1.CORS(主流的解决方案,推荐使用)
使用cors中间件解决跨域问题
步骤:
(1)运行npm install cors安装中间件
(2)使用const cors = require(‘cors’)导入中间件
(3)在路由之前调用app.use(cors())配置中间件

//一定要在路由之前,配置cors这个中间件,从而解决接口跨域问题
const cors = require('cors')
app.use(cors())

2.JSONP(有缺陷的解决方案:只支持GET请求)

3.什么事cors
在这里插入图片描述
4.CORS的注意事项
(1)CORS主要在服务器端进行配置,客户端浏览器无须做任何额外配置,即可开启CORS的接口
(2)CORS在浏览器中有兼容性,只有XMLHttpRequestLevel2的浏览器,才能正常访问开启了CORS的服务端接口(例如:IE10+、Chrome4+、FireFox3.5+)

5.CORS跨域资源共享

CORS响应头部 Access-Control-Allow-Origin

(1)允许访问所有该资源所有的外域URL

res.setHeader('Access-Control-Allow-Origin','*')

(2)只允许访问http://itcast.cn

res.setHeader('Access-Control-Allow-Origin','http://itcast.cn')

在这里插入图片描述
在这里插入图片描述
8.CORS请求的分类
客户端在请求CORS接口时,根据请求方式和请求头的不同,可以将CORS的请求分为两大类:
(1)简单请求
同时满足两个条件:
请求方式:GET、POST、HEAD三者之一
http头部信息超过以下几种字段:无自定义头部字段、Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width、Content-Type(只有三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)

(2)预检请求

只要符合以下任何一个请求
(1)请求方式GET POST HEAD之外的请求Method类型
(2)请求头中包含自定义头部字段
(3)向服务器发送了application/json格式的数据
浏览器与服务器正式通信之前,浏览器会先发送OPTION请求预检,以获取服务器是否允许该实际请求,所以这一次的OPTION请求称为预检请求,服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据

(3)两次请求的区别
简单请求特点:客户端与服务器只会发送一次请求
预检请求特点:客户端与服务器只会发送两次请求,OPTION请求预检成功后才会发送真正的请求。

5.JSONP接口
概念:浏览器端通过

6.创建JSONP接口

注意事项:项目中已经配置了CORS的跨域资源共享,为了防止冲突,必须在配置CORS中间件之前声明JSONP接口,否则JSONP接口会被处理成开启了CORS的接口
实现JSONP接口的步骤:
1.获取客户端发送过来色回调函数的名字
2.得到要通过JSONP形式发送给客户端的数据
3.根据前两步得到的数据,拼接出一个函数调用的字符串
4.把上一步得到色字符串,响应给客户端的<script标签进行解析执行

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值