vue基础--axios:初识 axios、发送ajax 请求、GET/POST请求、全局配置及请求响应拦截器、封装及跨域配置、创建服务器提供数据实践

目录

 一、初识 axios

1.1 什么是 axios

1.2 使用 axios 发送ajax 请求

二、axios方式GET/POST请求

2.1 发送GET请求

2.2 发送POST

三、全局配置及请求响应拦截器

3.1 全局配置

3.2 拦截器

四、封装及跨域配置

4.1 跨域解决方案

4.2 示例

五、创建服务器提供数据实践

5.1 前期准备


 一、初识 axios

1.1 什么是 axios

一个专门用于发送ajax请求的库

通过 npm install axios 安装

ajax原理?

浏览器window接口的XMLHttpRequest

特点 :

  • 支持客户端发送Ajax请求
  • 支持服务端Node.js发送请求
  • 支持Promise相关用法
  • 支持请求和响应的拦截器功能
  • 自动转换JSON数据
  • axios 底层还是原生js实现, 内部通过Promise封装的

语法:

  axios({
    method: '请求方式', // get/post
    url: '请求地址',
    data: { // 拼接到请求体的参数,post请求的参数
      xxx: yyy
    }, // 参数名和值会被axios拼接到请求体里
    params: { // 拼接到请求体的参数,get请求的参数
      xxx: yyy
    } // 参数名和值会被axios拼接到url?后面--查询字符串
  }).then(res => {
    console.log(res.data);// 后台返回去的结果
  }).catch(err => {
    console.log(err); // 后台报错返回
  })


1.2 使用 axios 发送ajax 请求

About.vue

<template>
  <div class="about">
    <h1 @click="handleClick">This is an about page</h1>
    <h1>{{name}}</h1>
  </div>
</template>

<script>
import {toRefs} from 'vue';
import {useStore} from 'vuex';

export default {
  name: 'About', 
  setup(){
  
    const store = useStore();

    const {name}=toRefs(store.state);

    const handleClick=()=>{
      store.dispatch('getData');
    }

    return{
      name,
      handleClick
    }
  }
}
</script>

Home.vue

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <h1>{{name}}</h1>
  </div>
</template>

<script>
import {toRefs} from 'vue';
import {useStore} from 'vuex';

export default {
  name: 'Home',
  setup(){
    const store = useStore();
    const {name}=toRefs(store.state);
    return{
      name
    }
  }
}
</script>

store/index.js

import { createStore } from 'vuex';
import axios from 'axios';

//VueX 数据管理框架
//VueX 创建了一个全局唯一的仓库,用来存放全局的数据
export default createStore({
    // 存放全局的数据
    state: {
        name: 'dell'
    },
    //mutation 里面只允许写同步代码,不允许写异步代码
    //commit和mutation作关联
    mutations: {
        //第四步,对应的 mutation 被执行
        changeName(state, str) {
            //第五步 在 mutation 里修改数据
            // this.state.name = 'lee';
            state.name = str;
        }
    },
    // dispatch 和 actions 作关联
    actions: {
        //第二步,store 感知到了你触发了一个叫做 change 的 action
        //执行 change()方法
        getData(store) {
            axios.get('https://www.fastmock.site/mock/ae8e9031947a302fed5f92425995aa19/jd/api/user/register')
                .then((res) => {
                    const msg = res.data.meaasge;
                    // console.log(msg);
                    //第三步,提交一个 commit,触发一个 mutation
                    store.commit('changeName', msg);
                })
        }
    },
    modules: {}
})


二、axios方式GET/POST请求

axios参考文档 :使用说明 · Axios 中文说明 · 看云

公共部分:

App.vue

<template>
  <div id="app">
    <HelloWorld />
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

2.1 发送GET请求

<template>
  <div>
    <h3>axios</h3>
    <p>{{info.title}}</p>
    <p>{{info.content}}</p>
  </div>
</template>

<script>
import axios  from "axios"

export default {
  name: 'HelloWorld',

  data () {
    return {
      info:{
        title:"",
        content:""
      }
    }
  },
  mounted () {
    //方式1 
    // 为给定 ID 的 user 创建请求
    // axios.get('http://iwenwiki.com/api/blueberrypai/getIndexChating.php')
    //  .then(res=> {
    //     // console.log(res.data);
    //     // console.log(res.data.chating);
    //     // console.log(res.data.chating[1]);
    //     if(res.status === 200){
    //       this.info.content=res.data.chating[1].content;
    //       this.info.title=res.data.chating[1].title;
    //     }
    //   })
    //   .catch(error=> {
    //     console.log(error);
    //   });

    //方式2  
      axios.get('http://iwenwiki.com:3000/search',{
        params:{
          keywords:"海阔天空"
        }
      })
      .then(res=> {
        console.log(res.data.result.songs);
      })
      .catch(error=> {
        console.log(error);
      });

  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

方式1,

 方式2,


2.2 发送POST

注意:
post接收参数的类型为:user_id=123&password=a45789
因此需要用到 querystring 来做类型转换

<template>
  <div>
    <h3>axios</h3>
  </div>
</template>

<script>
import axios  from "axios"
import qs from  "querystring"  

export default {
  name: 'HelloWorld',

  mounted () {
      axios.post('http://iwenwiki.com/api/blueberrypai/login.php', qs.stringify({
      user_id: 'iwen@qq.com',
      password: 'iwen123',
      verification:'crfvw'
    }))
    .then(res=> {
      console.log(res.data);
    })
    .catch(error=> {
      console.log(error);
    });

  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>


三、全局配置及请求响应拦截器

公共部分:

App.vue

<template>
  <div id="app">
    <HelloWorld />
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

3.1 全局配置

<template>
  <div>
    <h3>axios</h3>
    <p>{{info.title}}</p>
    <p>{{info.content}}</p>
  </div>
</template>

<script>
import qs from  "querystring"  

export default {
  name: 'HelloWorld',

  data () {
    return {
      info:{
        title:"",
        content:""
      }
    }
  },
  mounted () {
      // GET请求方式一
    this.$axios.get("http://iwenwiki.com:3000/search?keywords=海阔天空")
    .then(res =>{
      console.log(res.data);
    })
    .catch(error =>{
      console.log(error);
    })

    // GET请求方式二
    this.$axios.get("http://iwenwiki.com:3000/search",{
      params:{
        keywords:"泸沽湖"
      }
    }).then(res =>{
      console.log(res.data);
    }).catch(error =>{
      console.log(error);
    })

    //post请求
      this.$axios.post('/api/blueberrypai/login.php', qs.stringify({
      user_id:"iwen@qq.com",
      password:"iwen123",
      verification_code:"crfvw"
    }))
    .then(res=> {
      console.log(res.data);
    })
    .catch(error=> {
      console.log(error);
    });

  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

main.js

import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import axios from "axios"

//配置公共地址
axios.defaults.baseURL = 'http://iwenwiki.com';
// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';


//将其挂载到原型上,以便于引用
Vue.prototype.$axios = axios

Vue.config.productionTip = false

new Vue({
    render: h => h(App),
}).$mount('#app')


3.2 拦截器

<template>
  <div>
    <h3>axios</h3>
    <p>{{info.title}}</p>
    <p>{{info.content}}</p>
  </div>
</template>

<script>
import qs from  "querystring"  

export default {
  name: 'HelloWorld',

  data () {
    return {
      info:{
        title:"",
        content:""
      }
    }
  },
  mounted () {
      // GET请求方式一
    this.$axios.get("http://iwenwiki.com:3000/search?keywords=海阔天空")
    .then(res =>{
      console.log(res.data);
    })
    .catch(error =>{
      console.log(error);
    })

    // GET请求方式二
    this.$axios.get("http://iwenwiki.com:3000/search",{
      params:{
        keywords:"泸沽湖"
      }
    }).then(res =>{
      console.log(res.data);
    }).catch(error =>{
      console.log(error);
    })

    //post请求
      this.$axios.post('/api/blueberrypai/login.php', {
      user_id:"iwen@qq.com",
      password:"iwen123",
      verification_code:"crfvw"
    })
    .then(res=> {
      console.log(res.data);
    })
    .catch(error=> {
      console.log(error);
    });

  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

main.js

import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import axios from "axios"
import qs from 'querystring'

//配置公共地址
axios.defaults.baseURL = 'http://iwenwiki.com';
// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';


//拦截器
//请求拦截
axios.interceptors.request.use(
    config => {
        if (config.method === 'post') {
            //转换
            config.data = qs.stringify(config.data)
        }
        // console.log(config);
        return config
    },
    error => Promise.reject(error)
)

//响应拦截
axios.interceptors.response.use(
    response => {
        return response
    },
    error => Promise.reject(error)
)

//将其挂载到原型上,以便于引用
Vue.prototype.$axios = axios

Vue.config.productionTip = false

new Vue({
    render: h => h(App),
}).$mount('#app')


四、封装及跨域配置

 项目大致结构:

src里:

跨域产生的原因:

    域名、端口、二级域名等不同会产生跨域

4.1 跨域解决方案

1. 前端

    1. 生产环境

        jsonp

    2. 开发环境

        proxy代理方式

2. 后端

    cors方式


4.2 示例

App.vue

<template>
  <div id="app">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

main.js

import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

vue.config.js

module.exports = {
    devServer: {
        proxy: {
            '/api': {
                target: 'http://iwenwiki.com/',
                changeOrigin: true,
                pathRewrite: { // 路径重写
                    "^/api": ""
                }
            }
        }
    }
}

src/utils/request.js

import axios from "axios"
import qs from "querystring"

/**
 * 3.处理错误信息
 * status:状态码
 * info:具体信息
 */

const errorHandle = (status, info) => {
    switch (status) {
        case 400:
            console.log("语义错误");
            break;
        case 401:
            console.log("服务器认证失败");
            break;
        case 403:
            console.log("服务器请求拒绝执行");
            break;
        case 404:
            console.log("请检查网路请求地址");
            break;
        case 500:
            console.log("服务器发生意外");
            break;
        case 502:
            console.log("服务器无响应");
            break;
        default:
            console.log(info);
            break;
    }
}


/**
 * 1.创建Axios对象
 */

const instance = axios.create({
    // 公共配置
    // baseURL: "http://iwenwiki.com",//处理跨域时需要将其注释掉
    timeout: 5000,
    //跨域请求时,是否需要凭证
    // withCredentials: true
})


/**
 * 2.拦截器
 */
//请求拦截
instance.interceptors.request.use(
    config => {
        if (config.method === 'post') {
            // token:登陆信息凭证
            config.data = qs.stringify(config.data)
        }
        return config
    },
    error => Promise.reject(error)
)

// 响应拦截
instance.interceptors.response.use(
    // 完成了
    response => response.status === 200 ? Promise.resolve(response) : Promise.reject(response),
    error => {
        // 错误信息的处理
        const { response } = error;
        if (response) {
            errorHandle(response.status, response.info)
        } else {
            console.log("网络请求被中断了");
        }
    }
)

// get和post等请求方案

export default instance

src/api/index.js

import axios from "../utils/request"

/**
 * 所有的网络请都写在这里
 */

const base = {
    // baseUrl: "/",//非跨域
    baseUrl: "/api", //解决跨域
    banner: "/api/FingerUnion/list.php" // 首页banner路径
}

const api = {
    /**
     *  首页 banner位数据获取
     */
    getBanner() {
        return axios.get(base.baseUrl + base.banner)
    }
}

export default api

Helloword.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    
  </div>
</template>

<script>

import api from "../api"

export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  mounted(){
    api.getBanner().then(res =>{
      console.log(res.data);
    }).catch(error =>{
      console.log(error);
    })
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

非跨域,

跨域,


五、创建服务器提供数据实践

5.1 前期准备

npm install --save   axios  

npm install --save express

项目结构:

 

App.vue

<template>
  <div>
   <ServeDemo />
  </div>
</template>

<script>
import ServeDemo from "./components/ServeDemo.vue"

export default {
  name: 'App',
  components: {
    ServeDemo
  }
}
</script>

<style>
</style>

 ServeDemo.vue

<template>
  <div>
     hi
  </div>
</template>

<script>
import api from "../api"

export default {
    name:"ServeDemo",
    mounted () {
        api.getList({
            page:2
        }).then(res=>{
            console.log(res.data);
        }).catch(error=>{
            console.log(error);
        })
    }
}
</script>

<style>

</style>

vue.config.js

module.exports = {
    devServer: {
        proxy: {
            '/api': {
                target: 'http://localhost:3000/',
                changeOrigin: true,
                pathRewrite: { // 路径重写
                    "^/api": ""
                }
            }
        }
    }
}

serve/index.js

//引入express并创建express对象
const express = require("express");
const app = express();

// 引入
const router = require("./router");

//处理post请求
const bodyParser = require("body-parser");

//post
app.use(bodyParser.urlencoded({
    extended: true
}))

app.use("/", router);

//设置监听端口
app.listen(3000, () => {
    console.log("server running at port 3000");
})

serve/router.js

//引入express
const express = require("express");

//创建路由对象
const router = express.Router();

//get接收参数--引入url
const url = require("url");

//
const list = require("./data/list")

// get请求
router.get("/list", (req, res) => {
    const page = url.parse(req.url, true).query.page;
    // 发送数据
    res.send({
        status: 200,
        result: list,
        page
    })
})

// post请求
router.post("/login", (req, res) => {
    const username = req.body.username;
    const password = req.body.password;
    res.send({
        status: 200,
        username,
        password
    })
})

//导出  router
module.exports = router;

serve/data/list.js

module.exports = [
    {
        id:1001,
        name:"衣服"
    },
    {
        id:1002,
        name:"鞋子"
    },
    {
        id:1003,
        name:"电脑"
    }
]

src/api/index.js

import axios from "../utils/request"

const base = {
    // baseUrl: "http://localhost:3000",
    baseUrl: "/api",
    list: "/list"
}

const api = {
    getList(params) {
        return axios.get(base.baseUrl + base.list, {
            params
        })
    }
}

export default api;

src/utils/request.js

import axios from "axios"
import qs from "querystring"

/**
 * 处理错误信息
 * status:状态吗
 * info:具体信息
 */

const errorHandle = (status,info) =>{
    switch(status){
        case 400:
            console.log("语义错误");
            break;
        case 401:
            console.log("服务器认证失败");
            break;
        case 403:
            console.log("服务器请求拒绝执行");
            break;
        case 404:
            console.log("请检查网路请求地址");
            break;
        case 500:
            console.log("服务器发生意外");
            break;
        case 502:
            console.log("服务器无响应");
            break;
        default:
            console.log(info);
            break;
    }
}


/**
 * 创建Axios对象
 */

const instance = axios.create({
    // 公共配置
    // baseURL:"http://iwenwiki.com",
    timeout:5000,
    // withCredentials: true
})


/**
 * 拦截器
 */

instance.interceptors.request.use(
    config =>{
        if(config.method === 'post'){
            // token:登陆信息凭证
            config.data = qs.stringify(config.data)
        }
        return config
    },
    error => Promise.reject(error)
)

instance.interceptors.response.use(
    // 完成了
    response => response.status === 200 ? Promise.resolve(response) : Promise.reject(response),
    error =>{
        // 错误信息的处理
        const { response } = error;
        if(response){
            errorHandle(response.status,response.info)
        }else{
            console.log("网络请求被中断了");
        }
    }
)

// get和post等请求方案

export default instance

 通过  node index.js 运行服务器

通过 npm run  serve 运行前端

GET请求,

 POST请求,通过 postman来进行

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白小白从不日白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值