0


Vue的三种网络请求方式

文章目录


在进行 Vue 的网络请求之前,我们先写一些假数据:

users.json:

[{"id":1,"name":"张三"},{"id":2,"name":"李四"}]

1. 写法1:XMLHttpRequest发送请求

使用 XMLHttpRequest 请求 users.json 中的数据:

<divid="app"><ul><liv-for="item in users":key="item.id">{{item.name}}</li></ul></div><script>const vm =newVue({el:'#app',data:{users:[]},mounted(){const xhr =newXMLHttpRequest()// // true 表示发送异步请求
            xhr.open('get','/mock/users.json',true)// // 写法1// xhr.onreadystatechange = () => {//   // 0 - 4 xhr.readyState状态值 //   if (xhr.readyState === 4 && xhr.status === 200) {//     console.log(JSON.parse(xhr.responseText));//     this.users = JSON.parse(xhr.responseText)//   }// }// 写法2
            xhr.onload=()=>{
                console.log(JSON.parse(xhr.responseText));this.users =JSON.parse(xhr.responseText)}

            xhr.send(null)}})</script>

在这里插入图片描述

注意:上面介绍了两种方法,分别是

onreadystatechange

onload

,我们需要知道这两种方法的区别 。XMLHttpRequest 对象有一个属性 readyState,将其 (xhr.readyState) 打印后发现:进入

onreadystatechange

请求方式中时,可以打印其状态为2,状态为3,状态为4;进入

onload

之后,只出现了状态码4。也就是说,只有处于状态码4,请求已完成,响应已就绪的情况下,才会进入

onload

。只要进入

onload

请求中,一定是已经到4这个状态了。nreadystatechange()的定义是只要返回的状态码只要变化时就回调一次函数,而onload只有状态码为4时才能回调一次函数。

2. 写法2:fetch发送请求

使用 fetch 请求 users.json 中的数据:

<divid="app"><ul><liv-for="item in users":key="item.id">{{item.name}}</li></ul></div><script>const vm =newVue({el:'#app',data:{users:[]},// 兼容写法mounted(){fetch('/mock/users.json').then(ret=> ret.json()).then(json=>this.users = json)}// 高版本写法// async mounted() {//   let ret = await fetch('/mock/users.json')//   this.users = await ret.json()// }// 高版本装逼写法// async mounted() {//   this.users  = await (await fetch('/mock/users.json')).json// }})</script>

在这里插入图片描述

3. 写法3:axios请求库(Vue中推荐写法)

概述:

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和node.js中。能拦截请求和响应,自动转换JSON数据。axios也是vue作者推荐使用的网络请求库。

优势:

  1. 使用人群多
  2. 对 Ts 支持非常好
  3. 跨平台(nodejs、移动端)
  4. 基于 promise ,异步变同步,写法简单
  5. 添加了拦截器等封装好的函数,使用更加方便

使用方法:

<divid="app"><ul><liv-for="item in users":key="item.id">{{item.name}}</li></ul></div><scriptsrc="./js/axios.js"></script><script>const vm =newVue({el:'#app',data:{users:[]},mounted(){// 获取数据的简单使用
            axios.get('/mock/users.json').then(ret=>{
                console.log(ret.data);this.users=ret.data;})}})</script>

在这里插入图片描述

3.1 创建自己的服务器,模拟发送 get 和 post 请求

步骤1:

使用

npm init -y

初始化 node.js 配置文件

在这里插入图片描述

步骤2:

使用

npm i -S express

,安装 express

在这里插入图片描述

步骤3:

新建

app.js

,并且修改

package.json

文件如下

在这里插入图片描述

准备工作完成后,我们就可以书写服务端代码了:

app.js:

const express =require('express')const app =express()
app.listen(9000,()=>{
    console.log('http://localhost:9000')})// 中间件// 解决跨域 npm i -S cors 下载并写入配置文件
app.use(require('cors')())// post提供,内容为json格式
app.use(express.json())

app.get('/api/users',(req, res)=>{// 解决跨域问题// res.setHeader('Access-Control-Allow-Origin', '*')
    res.send({code:0,msg:'ok',data:{users:[{id:1,name:'张三'},{id:2,name:'李四'}],// 获取用户认证信息token: req.headers?.token
        }})})

app.post('/api/users',(req, res)=>{
    res.send({code:0,msg:'ok',// 把传过来的参数再返回出去data: req.body
    })})// patch/put// patch 增量更新// put 全量更新
app.put('/api/users/:id',(req, res)=>{
    res.send({code:0,msg:'ok',data: req.body
    })})

app.delete('/api/users/:id',(req, res)=>{// 返回 204 意味着不会返回任何数据// res.status(204).send({
    res.status(200).send({code:0,msg:'ok',data:{id: req.params.id
        }})})

前端获取数据:

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>vue学习使用</title><!-- 第1步: 引入vue库文件 --><scriptsrc="./js/vue.js"></script></head><body><!-- 第2步:挂载点 --><divid="app"><ul><liv-for="item in users":key="item.id">{{item.name}}</li></ul></div><!-- 第3步:实例化vue --><scriptsrc="./js/axios.js"></script><script>// axios全局配置  这里的地址会自动补全到 get 或 post 要请求的地址中// 可以写在配置文件中,方便修改
            axios.defaults.baseURL ='http://localhost:9000';// 全局设置网络请求超时时间,10s中还没请求到数据,就停止请求
            axios.defaults.timeout =10000const vm =newVue({el:'#app',data:{users:[]},mounted(){// 发送 get 请求// axios.get('/api/users').then(ret => {//     console.log(ret.data);//     // 只会监听当前 then 方法中是否有异常// }, () => console.log('有异常'))// 发送 post 请求// axios.post('/api/users', {//     name: '李四'// }).then(ret => {//     console.log(ret.data);// })// 发送 put 请求// axios.put('/api/users', {//     name: '李四 -- put'// }).then(ret => {//     console.log(ret.data);// })// 发送 delete 请求
                    axios.delete('/api/users/100').then(ret=>{
                        console.log(ret.data);})}})</script></body></html>

注意:

超时请求不到数据就报出异常,这种捕获异常的方式,会监听前面所有的 then 方法

axios.get('/api/users').then(ret => {
    console.log(ret.data);
}).catch(() => console.log('有异常'))

下面这种写法,只会监听当前 then 方法中是否有异常:

axios.get('/api/users').then(ret => {
    console.log(ret.data);
},() => console.log('有异常'))

3.2 网络请求时发送用户认证信息

有时候我们通过网络请求一个服务器的时候,需要携带一个用户认证信息,例如用户只有在登录状态下才能获取服务端的信息,否则不能获取数据,即所谓的接口认证。

那么这个登录的状态,即用户的认证信息,这是怎样传给服务器的呢?

我们会将用户的认证信息包含在前端的请求头当中,发送给服务端。

以 get 请求为例,服务端代码如下:

const express =require('express')const app =express()
app.listen(9000,()=>{
    console.log('http://localhost:9000')})// 中间件// 解决跨域
app.use(require('cors')())// post提供,内容为json格式
app.use(express.json())

app.get('/api/users',(req, res)=>{// 解决跨域问题// res.setHeader('Access-Control-Allow-Origin', '*')
    res.send({code:0,msg:'ok',data:{users:[{id:1,name:'张三'},{id:2,name:'李四'}],// 获取用户认证信息token: req.headers?.token
        }})})

前端代码如下:

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>vue学习使用</title><!-- 第1步: 引入vue库文件 --><scriptsrc="./js/vue.js"></script></head><body><!-- 第2步:挂载点 --><divid="app"><ul><liv-for="item in users":key="item.id">{{item.name}}</li></ul></div><!-- 第3步:实例化vue --><scriptsrc="./js/axios.js"></script><script>// axios全局配置  这里的地址会自动补全到 get 或 post 要请求的地址中// 可以写在配置文件中,方便修改
        axios.defaults.baseURL ='http://localhost:9000';// 全局设置网络请求超时时间,10s中还没请求到数据,就停止请求
        axios.defaults.timeout =10000const vm =newVue({el:'#app',data:{users:[]},mounted(){// 发送 get 请求
                axios.get('/api/users',{// 认证信息放在请求头发送headers:{token:'abc'}}).then(ret=>{
                    console.log(ret.data);// 只会监听当前 then 方法中是否有异常},()=> console.log('有异常'))}})</script></body></html>

在这里插入图片描述

注意:我们还可以使用全局配置来发送用户认证信息:

axios.defaults.headers.token = 'aaaaa'

,(请求头中的 token 因该删掉,否则会覆盖全局配置)但是这样的配置会给所有的请求方法都添加上用户认证信息,不能区别对待,也就是不能进行业务处理,不够灵活,所以我们需要用到拦截器。

3.3 请求拦截器

延续上面的案例,如果我们的需求是,如果是 get 方法发送,则在请求头中添加用户认证信息,其他方法不添加,则前端页面需要这样写:

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>vue学习使用</title><!-- 第1步: 引入vue库文件 --><scriptsrc="./js/vue.js"></script></head><body><!-- 第2步:挂载点 --><divid="app"><ul><liv-for="item in users":key="item.id">{{item.name}}</li></ul></div><!-- 第3步:实例化vue --><scriptsrc="./js/axios.js"></script><script>// axios全局配置  这里的地址会自动补全到 get 或 post 要请求的地址中// 可以写在配置文件中,方便修改
            axios.defaults.baseURL ='http://localhost:9000';// 全局设置网络请求超时时间,10s中还没请求到数据,就停止请求
            axios.defaults.timeout =10000// 请求拦截器
            axios.interceptors.request.use(config=>{if(config.method ==='get'){
                    config.headers.token ='abc'}// 请求拦截器中的回调函数中的config对象一定要return出去return config
            })const vm =newVue({el:'#app',data:{users:[]},mounted(){// 发送 get 请求
                    axios.get('/api/users',{// 认证信息放在请求头发送headers:{token:'abc'}}).then(ret=>{
                        console.log(ret.data);// 只会监听当前 then 方法中是否有异常},()=> console.log('有异常'))}})</script></body></html>

在这里插入图片描述

注意:请求拦截器中的回调函数中的config对象一定要return出去。

3.4 响应拦截器

作用:

对响应的数据做处理或判断

应用:

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>vue学习使用</title><!-- 第1步: 引入vue库文件 --><scriptsrc="./js/vue.js"></script></head><body><!-- 第2步:挂载点 --><divid="app"><ul><liv-for="item in users":key="item.id">{{item.name}}</li></ul></div><!-- 第3步:实例化vue --><scriptsrc="./js/axios.js"></script><script>// axios全局配置  这里的地址会自动补全到 get 或 post 要请求的地址中// 可以写在配置文件中,方便修改
            axios.defaults.baseURL ='http://localhost:9000';// 全局设置网络请求超时时间,10s中还没请求到数据,就停止请求
            axios.defaults.timeout =10000

            axios.defaults.headers.token ='aaaaa'// 响应拦截器
            axios.interceptors.response.use(res=>{// 这里是未被处理过的响应数据
                console.log(res);// 解套,减少数据的调用层级,直接返回 res.dataif(res.data.code ==0)return res.data
                // 这里是做了全局的网络错误处理alert('有错')},err=> Promise.reject(err))const vm =newVue({el:'#app',data:{users:[]},mounted(){// 发送 get 请求
                    axios.get('/api/users').then(ret=>{// 这里返回的时解套后的数据(已经被响应拦截器处理过了)
                        console.log(ret);// 只会监听当前 then 方法中是否有异常},()=> console.log('有异常'))}})</script></body></html>

在这里插入图片描述

3.5 案例:用户管理

服务端:

// 服务端代码:具备增删改查、数据源const express =require('express')const app =express()
app.listen(9000,()=>{
    console.log('http://localhost:9000')})// 解决跨域
app.use(require('cors')())// post提供,内容为json格式
app.use(express.json())// 声明一个变量,只要服务不重启,我就永久存储(放入内存了)let users =[{id:1,name:'张三',age:10},{id:2,name:'李四',age:20}]// 响应get请求
app.get('/api/users',(req, res)=>{
    res.send({code:0,msg:'ok',// 如果请求成功就返回对应的usersdata: users
    })})// 增添数据
app.post('/api/users',(req, res)=>{// 接受post提交过来的数据,用当前时间作为主键idconst user ={...req.body,id: Date.now()}// 添加数据
    users.push(user)
    res.send({code:0,msg:'ok',// 如果请求成功就返回对应的usersdata: users
    })})// 修改数据
app.put('/api/users/:id',(req, res)=>{// 接受修改的id号let id = req.params.id
    // 接受put提交过来的数据
    users = users.map(item=>(item.id == id ?{...item,...req.body }: item));
    res.send({code:0,msg:'ok',data: users
    })})// 删除数据
app.delete('/api/users/:id',(req, res)=>{// 接受修改的id号let id = req.params.id
    users = users.filter(item=> item.id != id)
    res.send({code:0,msg:'ok',data: users
    })})

客户端:

http.js(axios发送请求):

// 解套处理(响应拦截器),直接返回所需数据,降低层级
axios.interceptors.response.use(res=> res.data,err=> Promise.reject(err))// 请求拦截器
axios.interceptors.request.use(config=>{
        config.baseURL ='http://localhost:9000'// 请求超时拦截
        config.timeout =10000return config
    },err=> Promise.reject(err))// 封装 axios 中的方法constget=url=> axios.get(url)constpost=(url, data ={})=> axios.post(url, data)constput=(url, data ={})=> axios.put(url, data)constdel=url=> axios.delete(url)

index.html:

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>vue学习使用</title></head><body><divid="app"><button@click="add">添加用户</button><hr><ul><!-- 条件渲染 --><!-- template标签 影子标签,可以占位,可以读取指令,但不会被解析成html,可以使有效的标签中没有不想要的指令 --><templatev-if="users.length===0"><li>数据加载中...</li></template><templatev-else><liv-for="item in users":key="item.id"><span>{{item.name}}</span><span><button@click="edit(item.id)">修改</button></span><span><button@click="del(item.id)">删除</button></span></li></template></ul></div><scriptsrc="./js/vue.js"></script><scriptsrc="./js/axios.js"></script><scriptsrc="./utils/http.js"></script><script>const vm =newVue({el:'#app',data:{// 定义数据源users:[]},asyncmounted(){// this.users = await (await get('/api/users')).datalet users =awaitget('/api/users')this.users = users.data
                },methods:{asyncadd(){let users =awaitpost(`/api/users`,{name: Date.now()+''})this.users = users.data
                    },asyncedit(id){let users =awaitput(`/api/users/${id}`,{name: Date.now()+''})this.users = users.data
                    },asyncdel(id){let users =awaitdel(`/api/users/${id}`)this.users = users.data
                    }}})</script></body></html>

在这里插入图片描述


本文转载自: https://blog.csdn.net/weixin_45605541/article/details/126732232
版权归原作者 月光晒了很凉快 所有, 如有侵权,请联系我们删除。

“Vue的三种网络请求方式”的评论:

还没有评论