05月26, 2021

Vue实战(七)-- Axios

七、Axios

涉及的知识:

  • ES6: Promise
  • ES7: async 和 await
  • http协议
  • ajax
  • 跨域

使用axios库发送ajax请求

使用axios

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。 https://www.kancloud.cn/yunye/axios/234845

下载依赖

$ npm install axios --save

其中--save在新版本的npm中不再被需要了,直接npm install axios即可

引入

import axios from ‘axios’

示例:请求阿里云新闻频道数据

我们使用阿里云市场中的api作为新闻数据来源

在真实的项目中,通常是使用自己服务器的api

阿里云:https://www.aliyun.com/

新闻api:https://market.aliyun.com/products/57126001/cmapi011150.html

1、在工程中创建services文件夹,并创建相应的service

相关API,在阿里云新闻api中查询

import axios from 'axios'

export async function getNewsChannels(){
    let resp = await axios.get("http://ali-news.showapi.com/channelList",{
        headers:{
            Authorization:`APPCODE 176eadd6b4654cd5a9328c74a9025c37`
        }
    });
    return resp.data.showapi_res_body.channelList;
}

getNewsChannels方法帮我们返回了新闻频道数据

2、在对应的组件中显示数据

创建Channels.vue组件

<template>
  <div> 
    <el-menu
      :default-active="activeIndex"
      class="el-menu-demo"
      mode="horizontal"
      @select="handleSelect"
    >
      <el-menu-item :index="i.toString()
      " v-for="(item,i) in showChannels" :key="item.channelId">{{item.name}}</el-menu-item>
      <el-menu-item><a @click="handleFold()">{{isFold?"折叠":"展开"}}</a></el-menu-item>
    </el-menu>
  </div>
</template>

<script>
import {getNewsChannels} from '../services/NewsService'
export default {
  data() {
    return {
      activeIndex:"0",
      isFold:false,
      channels:[],
    };
  },
  methods: {
    handleFold(){
      this.isFold = !this.isFold;
    },
    handleSelect(key, keyPath) {
      console.log(key, keyPath);
    },
  },
  computed:{
    showChannels(){
      if(this.isFold){
        return this.channels;
      }
      else{
        return this.channels.slice(0,6);
      }

    },
  },
  async created() {
    let resp = await getNewsChannels();
    console.log(resp);
    this.channels = resp;
  },
};
</script>

<style></style>

3、在App.vue中引入组件

<template>
  <div id="app">
    <el-container>
      <el-header><Channels></Channels></el-header>
      <el-main>Main</el-main>
    </el-container>
  </div>
</template>

<script>
import Header from "./components/Channels";
export default {
  name: "App",
  components: { Channels },
};
</script>

本地测试跨域问题

上面是为了比较轻松的解决后台数据问题,因此直接访问了阿里云的后台数据,同样,我们自己的后台数据同样可以获取,比如在NewsService有下面的代码:

export async function getUsersLocal(){
    let resp = await axios.get("/api/springboot181/user/list");
    return resp;
}

可以在任意地方测试一下数据是否可以获取,比如直接在main.js引用测试一下

import {getUsersLocal} from './services/NewsService'

getUsersLocal().then((resp)=>{
  console.log(resp);
})

大家忽略一个问题,本地服务器,通过ajax直接访问了阿里云上的数据,其实是一个跨域的访问,简单来了域名和端口不一样,ajax请求就会出现问题

如果我们在做开发的时候,比如通过 IDEA 启动了 tomcat,比如地址是http://127.0.0.1:8080,这是后台要访问的地址

而我们做VUE前台测试的时候会通过npm run serv命令,启动一个前台服务器,比如地址是http://127.0.0.1:8081,我们需要使用前台使用axios直接访问后台接口数据的时候,就会出现下面的问题:

-w1305

这就是跨域的问题,要解决这个问题,有很多办法 1、直接在应用服务器处理,我们远程访问阿里云数据的时候没有报出这个错误,其实就是阿里云后台的服务器已经处理了这个问题,这需要修改后台应用服务器的配置...

2、修改发送和响应的头文件信息,屏蔽浏览器跨域的问题 比如在前台访问后台时,加入下面的代码:

export async function getNewsChannels(){
    var resp = await axios.get("http://127.0.0.1:8080/mmybatis/user.do",{
            headers:{
                'Content-Type':'application/x-www-form-urlencoded'
            }
    });
    return resp;
}

主要是请求头参数:

headers:{
    'Content-Type':'application/x-www-form-urlencoded'
}

后台代码中也需要加入代码:

response.setHeader("Access-Control-Allow-Origin", "*");

这种修改比较简单易懂,但是麻烦点是每个请求都需要加上请求头,而且服务器代码也需要做相应的修改,并不适合开发

3、使用webpack模式的代理 VUE导入的axios已经考虑到了跨域的问题,所以,我们可以直接使用VUE配置文件进行代理,解决跨域的问题,简单来说,就是把URL做了一次转换

需要在根目录中加入文件vue.config.js

vue.config.js

module.exports = {
    lintOnSave:false, //是否在浏览器中显示代码检查的错误
    devServer:{
        port:8081, //设置端口号,如果默认8080不需要设置,这里设置8081主要是为了不要和后台tomcat的8080接口冲突
        proxy: { //设置代理
            "/api": { // /api 匹配项,匹配拦截;
                target: "http://localhost:8080", //被请求的地址,需要被代理的地址
                changeOrigin: true,//允许跨域
                pathRewrite: {
                    "^/api": "" //重写配置,被代理的接口会多一个‘/api’的前缀,而原本的接口是没有的,所以需要通过此项来将接口的前缀‘/api’转换为‘’
                }
            }
        }
    }
}

这个文件在服务启动的时候会自动加载,不需要我们过多配置,但是,他的实际作用其实就是URL的改写,所以,在我们访问后台接口地址的时候,需要作出相应的改变

var resp = await axios.get("/api/mmybatis/user.do");

本文链接:http://www.yanhongzhi.com/post/VueInAction-7.html

-- EOF --

Comments