[Vue 牛刀小试]:第十五章 - 传统开发模式下的 axios 使用入门

 1、前言

  在没有接触 React、Angular、Vue 这类 MVVM 的前端框架以前,没法抛弃 Jquery 的重要理由,除了优秀的前端 DOM 元素操做性之外,可以很是便捷的发起 http 请求也占有很是重要的地位。html

  既然咱们已经开始使用 Vue 进行前端开发,抛弃了对页面 DOM 元素的操做,难道,为了方便的发起 http 请求,还须要在项目中加载 jquery 或者是手动建立 http 请求吗?前端

  答案固然是不用的,做为目前主流的前端框架,开发者、社区早已经为咱们提供好了解决方案。随着 Vue 做者尤雨溪宣布再也不维护 vue-resource,转而推荐你们使用 axios,目前在 Vue 社区中 axios 开始占据 http 库的主导地位,因此这一章咱们就介绍下如何使用 axios 发起 http 请求。vue

  学习系列目录地址:http://www.javashuo.com/article/p-bzzucmub-ba.htmlnode

  仓储地址(前端):https://github.com/Lanesra712/VueTrial/blob/master/chapter02-bronze/front/axios.htmljquery

  仓储地址(后端):https://github.com/Lanesra712/VueTrial/tree/master/chapter02-bronze/rear/Samplewebpack

 2、干货合集

  axios 是一个基于 Promise 的 http 客户端,能够用于浏览器和 node.js。官方文档对于 axios 库的使用方法已经写的很清楚了,因此这里只介绍如何与 Vue 进行结合,从而使用 axios 发起 http 请求。ios

  这一章会涉及到简单的先后端的数据交互,做为一名 .NETer,本篇文章将采用 ASP.NET Core Web API 做为后端服务,你能够根据本身的喜爱进行选择。固然,若是你以前并无接触事后端,不知道怎么选择的话,推荐你尝试 .NET Core,示例的后端项目我也会同步放在 Github 上。git

   PS:在后端模板项目上,我会添加对于 Swagger API 文档的支持,以及在后端程序中进行配置跨域请求,从而容许后端接口能够接受跨域请求的访问。这些内容并不会在本篇文章中展示,若是你须要详细了解,你能够查看另外一个系列的文章(ASP.NET Core 项目实战)那里会介绍一些关于 ASP.NET Core 项目的开发,两个系列相辅相成,后续全部涉及到先后端的交互开发,所有在此系列(ASP.NET Core 项目实战)中进行呈现。github

  一、加载

  同目前的前端发展方向相同,axios 能够从 npm、yarn、bower 这种前端包管理工具中进行下载,同时,也提供了 cdn 连接,方便咱们在传统的项目中进行使用。web

// 使用 npm 加载
npm install axios

// 使用 bower 加载
bower install axios

// 使用 yarn 加载
yarn add axios

  在这篇文章中,我仍是与以前同样,采用下载源文件的方式进行使用,在后续的前端框架搭建完成后再改用前端包管理工具进行加载。

// 使用 cdn 加载
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

  二、get & post

  相比于 put 请求和 delete 请求,get 请求和 post 请求是咱们最经常使用的两个方法,一个很常见的使用场景,咱们经过 get 请求来搜索数据,经过 post 请求来提交数据。

  在示例的后端接口中,提供了五个接口方法,分别对应了 get、post、put、delete 这四个 HTTP 谓词。put 和 delete 对应的接口方法这里并无实现,这篇文章主要使用的是 get 和 post 谓词对应的三个接口。

  2.一、获取全部的用户数据(/api/user)

  get 请求,加载所有的用户数据,按照建立时间进行降序排列。

  2.二、根据搜索条件搜索用户数据(/api/user/query)

  get 请求,根据用户输入框输入的数据,从所有的用户数据中查找出符合条件的数据,由于这里会存在多个查询条件,其实并不太符合 Restful 的接口设计,因此这里我采用 ASP.NET Core 中的特性路由的方式,指定此路由为专门的数据查询接口。

  2.三、新增用户数据(/api/user)

  post 请求,提交一条新的用户数据,由于是采用 Restful 风格的接口设计,因此请求的地址与获取全部的用户数据相同,仅仅是 http 谓词的不一样。

  最终实现的前端页面以下所示,页面第一次加载时会加载所有的用户数据;当用户点击搜索按钮时,会根据顶部的三个输入框中的值,从用户数据中进行筛选;当点击新增按钮时,则会根据 Name 和 Email 输入框中的值新增一条新的用户数据。

  首先咱们须要在页面加载的时候请求后端接口,去获取咱们的用户数据,这里咱们在 Vue 实例的 methods 中定义一个 getList 方法,在这个方法中咱们去请求后端接口。

  在以前学习 Vue 的生命周期钩子函数时咱们了解到,在 created 钩子函数中,对于 Vue 实例的 data 和 methods 已经初始化完成,此时,整个 Vue 实例已经初始化完成。可是,初始化完成的 Vue 实例没有与 DOM 进行绑定。因此,若是咱们想要在页面初始加载时就渲染出整个用户信息表格,created 函数是可以调用 getList 方法最先的一个钩子函数。

  在 axios 中,咱们发起一个 http 请求后,在 then 回掉方法中进行请求成功后的数据处理,在 catch 回掉方法中捕获请求失败的信息。这里的 then 方法就至关于咱们在 Jquery 中使用 ajax 时的 success 回调方法,而 catch 方法则是 error 回调。

axios.get('http://localhost:5000/api/user')
    .then(function (response) {
        console.log(response)
    }).catch(function (error) {
        console.log(error)
    })

  从接口打印出的返回结果能够看到,接口返回的 response 中包含了五部分的信息。这里 data 属性显示的就是整个的用户数据集合,在实际使用中,你须要与 http 响应状态码进行结合,考虑若是后端出现错误如何使前端知晓,从而相对友好的通知用户。

{
  // 后端接口返回的数据
  data: {},

  // 服务端接口返回的 HTTP 状态码
  status: 200,

  // 服务端接口返回的 HTTP 状态信息
  statusText: 'OK',

  // 后端接口返回的响应 header 信息
  headers: {},

  // axios 发起的接口请求时的配置信息
  config: {},

  // 接口响应的请求信息
  request: {}
}

  针对 axios 发起请求时的配置信息,咱们能够本身进行配置。例如咱们能够设置请求的接口域名是什么,设置 post 请求时的 Content-Type,或者针对先后端数据交互时常用的 Jwt Token 验证,咱们能够在请求的 header 中添加 token 信息,从而经过后端的权限验证。

axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

  当咱们获取到全部的用户数据后,咱们就能够将结果值赋值给咱们 Vue 实例中的 users 数据集合对象(这个 users 须要你事先在 Vue 实例的 data 中进行提早定义好)。

axios.get('http://localhost:5000/api/user')
    .then(function (response) {
        console.log(response)
        this.users = response.data
    }).catch(function (error) {
        console.log(error)
    })

  若是你按照上面的写法进行赋值,你会发现页面上并无按照咱们的想法渲染出数据。既然咱们已经获取到了后端接口返回的数据值,那么这里的问题就可能出如今赋值这上面。咱们能够在 then 回调中打印 this.users 看看。

  能够看到,这里的 this 指向的实际上是浏览器的 window 对象,所以咱们给 this.users 赋值最终是赋值到 window 对象上了。由于是 this 指向出了问题,因此这里我就直接采用箭头函数的方式进行数据赋值,最终的实现代码以下所示。

var vm = new Vue({
    el: '#app',
    data: {
        id: '',
        name: '',
        email: '',
        users: []
    },
    created() {
        this.getList()
    },
    methods: {
        getList() {
            axios.get('http://localhost:5000/api/user')
                .then(response => {
                    this.users = response.data
                }).catch(error => {
                    console.log(error)
                })
        }
    },
});

  搜索按钮的功能与获取全部用户信息的代码比较类似,这里咱们须要将搜索的参数添加到 get 请求中。从下图的浏览器控制台中能够看到,当点击查询按钮以后,咱们添加的参数会以 query 查询字符串的方式添加到请求的 url 地址上。

var vm = new Vue({
    el: '#app',
    data: {
        id: '',
        name: '',
        email: '',
        users: []
    },
    methods: {
        search() {
            axios.get('http://localhost:5000/api/user/query', {
                params: {
                    id: this.id,
                    name: this.name,
                    email: this.email,
                }
            }).then(response => {
                this.users = response.data
            }).catch(error => {
                console.log(error)
            })
        }
    },
});

  与 get 请求类似,使用 axios 发起 post 请求也是在 then 回掉方法中获取接口返回值,在 catch 回掉方法中捕获错误信息。

var vm = new Vue({
    el: '#app',
    data: {
        id: '',
        name: '',
        email: '',
        users: []
    },
    methods: {
        getList() {
            axios.get('http://localhost:5000/api/user')
                .then(response => {
                    this.users = response.data
                }).catch(error => {
                    console.log(error)
                })
        },
        add() {
            axios.post('http://localhost:5000/api/user', {
                name: this.name,
                email: this.email,
            }).then(response => {
                console.log(response)
                this.getList()
            }).catch(error => {
                console.log(error)
            })
        }
    },
});

  就像咱们使用 jquery 发起 ajax 请求同样,咱们可使用 $.ajax/$.post 方法去发起一个 get/post 请求,也能够在 $.ajax 方法中经过指定请求的 type 类型来肯定咱们是以 get 请求仍是 post 请求的方式执行,在 axios 中也提供了类似的功能。

// get 请求
axios({
  method: 'get',
  url: 'http://localhost:5000/api/user'
})

// post 请求
axios({
  method: 'post',
  url: 'http://localhost:5000/api/user',
  data: {
    name: this.name,
    email: this.email,
  }
}); 

  整个前端页面完整的示例代码以及实现的效果以下所示。

<div id="app">
    <div class="card border-info mb-3" style="margin-top: 20px;">
        <div class="card-header text-info">
            <b>用户信息</b>
        </div>
        <div class="card-body text-info form-inline">
            <div class="form-row">
                <div class="form-group">
                    <div class="input-group mb-2 mr-sm-2">
                        <div class="input-group-prepend">
                            <div class="input-group-text text-info"> Id </div>
                        </div>
                        <input type="text" class="form-control" id="id" v-model="id" autocomplete="off">
                    </div>
                </div>
                <div class="form-group">
                    <div class="input-group mb-2 mr-sm-2">
                        <div class="input-group-prepend">
                            <div class="input-group-text text-info"> Name </div>
                        </div>
                        <input type="text" class="form-control" id="name" v-model="name" autocomplete="off">
                    </div>
                </div>
                <div class="form-group">
                    <div class="input-group mb-2 mr-sm-2">
                        <div class="input-group-prepend">
                            <div class="input-group-text text-info"> Email </div>
                        </div>
                        <input type="email" class="form-control" id="email" v-model="email" autocomplete="off">
                    </div>
                </div>
                <div class="form-group">
                    <a class="btn btn-info" href="#" role="button" @click="search">搜索</a>
                    <a class="btn btn-success" href="#" role="button" @click="add">新增</a>
                </div>
            </div>

        </div>
    </div>

    <table class="table table-striped table-bordered table-hover text-info">
        <thead class="thead-inverse">
            <tr>
                <th>Id</th>
                <th>Name</th>
                <th>Email</th>
                <th>Created On</th>
            </tr>
        </thead>
        <tbody>
            <tr v-for="item in users" :key="item.id">
                <td scope="row">{{item.id}}</td>
                <td>{{item.name}}</td>
                <td>{{item.email}}</td>
                <td>{{item.createdTime}}</td>
            </tr>
        </tbody>
    </table>

</div>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            id: '',
            name: '',
            email: '',
            users: []
        },
        created() {
            this.getList()
        },
        methods: {
            getList() {
                axios.get('http://localhost:5000/api/user')
                    .then(response => {
                        this.users = response.data
                    }).catch(error => {
                        console.log(error)
                    })
            },
            search() {
                axios.get('http://localhost:5000/api/user/query', {
                    params: {
                        id: this.id,
                        name: this.name,
                        email: this.email,
                    }
                }).then(response => {
                    this.users = response.data
                }).catch(error => {
                    console.log(error)
                })
            },
            add() {
                axios.post('http://localhost:5000/api/user', {
                    name: this.name,
                    email: this.email,
                }).then(response => {
                    console.log(response)
                    this.getList()
                }).catch(error => {
                    console.log(error)
                })
            }
        },
    });
</script>

  三、拦截器

  在先后端分离的项目中,咱们通常采用 Jwt token 的方式进行权限控制。前端在获取数据以前,须要从后端获取到 token 令牌。当前端获取到后端回传的 token 信息后,咱们须要将此 token 信息保存下来,此后全部的请求都须要在请求的 header 信息中添加此 token 信息。那么,能不能有一种方式能够在触发后端验证以前,统一的进行 token 信息校验,当判断没有包含 token 信息以后,前端直接跳转到登陆页面。

  在 axios 中,咱们能够将此类操做放置到拦截器中。你能够将 axios 中的拦截器当作是 ASP.NET Core 中的 Filters 过滤器,例如,这里的需求,咱们彻底能够将获取到的 token 信息置于 request 请求拦截器中,在发起的每一次 http 请求时去校验是否包含 token 信息,当没有包含 token 信息时,就能够直接跳转到登陆页面。

  这里由于我并无实现后端 token 验证,因此这里就只是进行一个演示,你能够从浏览器的控制台中看到只要咱们发起一个 http 请求,就会输出的咱们打印的信息。

// request 请求拦截
axios.interceptors.request.use(function (request) {
    // 对 request 进行拦截
    if(true){
        console.log('跳转到登陆页面')
    }
    return request;
}, function (error) {
    // 在错误请求时进行操做
    return Promise.reject(error);
});
  

  既然有针对发起 request 请求时的拦截器,毫无疑问,对于获取到接口返回的 response 信息,咱们一样可使用拦截器进行拦截。例如,在定义 restful 接口时,咱们通常会根据 http 响应状态码去反映接口的调用是否成功。在每个经过 axios 发起请求的 then 回掉方法中,咱们都须要对获取到响应状态码进行判断,判断接口的调用是否成功。

  当咱们使用拦截器后,咱们彻底能够在针对 response 的拦截器中进行统一的判断。例如,当调用接口不成功时,http 响应状态码为 400,同时返回错误信息,咱们彻底能够在拦截器中进行判断,当全部的接口响应状态码为 400 时,弹出后端返回的错误信息。

// response 请求拦截
axios.interceptors.response.use(function (response) {
    // 对 response 进行拦截
    switch (response.status) {
        case 200:
            console.log('接口访问成功')
            break
        case 400:
            console.log('提示错误信息')
            break
        case 401:
            console.log('重定向到登陆页面')
            break
    }

    return response;
}, function (error) {
    // 在错误请求时进行操做
    return Promise.reject(error);
});

 3、总结

   这篇文章主要是简单介绍如何使用 axios 去实现发起一个 http 请求。至此,在现阶段的 Vue 学习使用中,对于一些基础知识点就已经完成了一个初步的梳理,接下来,从下一章开始,我会从 0 开始经过 Vue CLI 去搭建一个前端的项目模板,由于本身并非一个前端开发人员,我的的关注点还在于 .NET Core 后端,因此这里可能并不会涉及到 webpack 相关的知识点。同时,一些在以前的学习中没有涉及到的知识点也会在后续的文章中进行补充。以后,就像开篇时所说的那样,Vue.js 牛刀小试 和 ASP.NET Core 项目实战 相辅相成,后期的关注点将聚焦于如何经过 ASP.NET Core 和 Vue 进行先后端开发,欢迎持续关注~~~

相关文章
相关标签/搜索