使用vue时如何发送请求?
答:ajax,不过vue不使用jquery,那么需要引入一些HTTP库工具,使用其中封装好的请求方法即可
superagent或者Axios(主流)
使用文档
https://www.kancloud.cn/yunye/axios/234845
https://www.jianshu.com/p/1432e0f29abd
首先要安装相应的工具
运行命令
npm install xxx -D
xxx替换为对应的组件名
然后在src下的config目录新建js文件
假如现在使用的是superagent
api.js
// 配置API接口地址
var root = 'https://cnodejs.org/api/v1';
// 引用superagent
var request = require('superagent');
// 自定义判断元素类型JS
function toType(obj) {
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
// 参数过滤函数
function filter_null(o) {
for (var key in o) {
if (o[key] == null) {
delete o[key]
}
if (toType(o[key]) == 'string') {
o[key] = o[key].trim()
if (o[key].length == 0) {
delete o[key]
}
}
}
return o
}
/*
接口处理函数
这个函数每个项目都是不一样的,我现在调整的是适用于
https://cnodejs.org/api/v1 的接口,如果是其他接口
需要根据接口的参数进行调整。参考说明文档地址:
https://cnodejs.org/topic/5378720ed6e2d16149fa16bd
*/
function _api_base(method, url, params, success, failure) {
var r = request(method, url).type('text/plain')
if (params) {
params = filter_null(params);
if (method === 'POST' || method === 'PUT') {
if (toType(params) == 'object') {
params = JSON.stringify(params);
}
r = r.send(params)
} else if (method == 'GET' || method === 'DELETE') {
r = r.query(params)
}
}
r.end(function(err, res) {
if (err) {
alert('api error, HTTP CODE: ' + res.status);
return;
};
if (res.body.success == true) {
if (success) {
success(res.body);
}
} else {
if (failure) {
failure(res.body);
} else {
alert('error: ' + JSON.stringify(res.body));
}
}
});
};
// 返回在vue模板中的调用接口
export default {
get: function(url, params, success, failure) {
return _api_base('GET', root + '/' + url, params, success, failure)
},
post: function(url, params, success, failure) {
return _api_base('POST', root + '/' + url, params, success, failure)
},
put: function(url, params, success, failure) {
return _api_base('PUT', root + '/' + url, params, success, failure)
},
delete: function(url, params, success, failure) {
return _api_base('DELETE', root + '/' + url, params, success, failure)
},
}
这是原博作者封装好的请求方法,开头的api地址是我们项目的基础请求地址头
这里填的是cnodejs.org提供的api接口
使用时只需要
先在启动入口里全局配置好
import api from './config/api'
Vue.prototype.$api=api
这两行的意思大概就是把api.js文件注册到全局,然后可以通过 $api.方法名 调用该文件里的方法。
如
<script type="text/javascript">
import Header from '../components/header'
import Footer from '../components/footer'
export default{
components:{Header,Footer},
data(){
return{
lists:[]
}
},
created(){
this.get_data()
},
methods:{
get_data:function(params){
var v=this
if(!params) params={}
v.$api.get('topics',params,function(r){
v.lists=r.data;
})
},
},
}
</script>
created是该页面创建时执行的方法,params是传入的参数,’topics’是请求的地址,r是成功执行时返回的数据
然后该页面的template块为
<template>
<div>
<Header></Header>
<ul class="list">
<li v-for="item in lists">
<time v-text="$fortime.goodTime(item.create_at)"></time>
<router-link :to="'/content/' + item.id">{{item.title}}</router-link>
</li>
</ul>
<Footer></Footer>
</div>
</template>
fortime是我注册的工具类,用来格式化时间
router-link相当于a标签,请求的地址是/content/加上item的id
接下来写content里的内容,这次使用axios工具
一样,先install,创建一个index.js写入
// 配置API接口地址
var root = '/api/v1'
// 引用axios
var axios = require('axios')
// 自定义判断元素类型JS
function toType (obj) {
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
// 参数过滤函数
function filterNull (o) {
for (var key in o) {
if (o[key] === null) {
delete o[key]
}
if (toType(o[key]) === 'string') {
o[key] = o[key].trim()
} else if (toType(o[key]) === 'object') {
o[key] = filterNull(o[key])
} else if (toType(o[key]) === 'array') {
o[key] = filterNull(o[key])
}
}
return o
}
/*
接口处理函数
这个函数每个项目都是不一样的,我现在调整的是适用于
https://cnodejs.org/api/v1 的接口,如果是其他接口
需要根据接口的参数进行调整。参考说明文档地址:
https://cnodejs.org/topic/5378720ed6e2d16149fa16bd
主要是,不同的接口的成功标识和失败提示是不一致的。
另外,不同的项目的处理方法也是不一致的,这里出错就是简单的alert
*/
function apiAxios (method, url, params, success, failure) {
if (params) {
params = filterNull(params)
}
axios({
method: method,
url: url,
data: method === 'POST' || method === 'PUT' ? params : null,
params: method === 'GET' || method === 'DELETE' ? params : null,
baseURL: root,
withCredentials: false
})
.then(function (res) {
if (res.data.success === true) {
if (success) {
success(res.data)
}
} else {
if (failure) {
failure(res.data)
} else {
window.alert('error: ' + JSON.stringify(res.data))
}
}
})
.catch(function (err) {
let res = err.response
if (err) {
window.alert('api error, HTTP CODE: ' + res.status)
}
})
}
// 返回在vue模板中的调用接口
export default {
get: function (url, params, success, failure) {
return apiAxios('GET', url, params, success, failure)
},
post: function (url, params, success, failure) {
return apiAxios('POST', url, params, success, failure)
},
put: function (url, params, success, failure) {
return apiAxios('PUT', url, params, success, failure)
},
delete: function (url, params, success, failure) {
return apiAxios('DELETE', url, params, success, failure)
}
}
!这里不直接用原api地址是因为cnode.js的接口处理的很好,解决了跨域的问题。实际项目中,很多接口不允许跨域请求。为了解决这个问题,采用webpack的代理的方式
在根目录的config文件夹下打开index.js,找到proxyTable这一行,里面就是我们要填的代理地址
这里我们写的是
proxyTable: {
'/api/v1/**':{
target: 'https://cnodejs.org',
secure: false,
changeOrigin: false,
}
},
然后在main.js里注册
import aapi from './config/index'
Vue.prototype.$axapi=aapi
然后使用
<template>
<div>
<myHeader></myHeader>
<h2 v-text="dat.title"></h2>
<p v-if=dat.author>作者:{{dat.author.loginname}} 发表于:{{$fortime.goodTime(dat.create_at)}}</p>
<hr>
<article v-html="dat.content"></article>
<h3>网友回复:</h3>
<ul>
<li v-for="i in dat.replies">
<p>评论者:{{i.author.loginname}} 评论于:{{$fortime.goodTime(i.create_at)}}</p>
<article v-html="i.content"></article>
</li>
</ul>
<myFooter></myFooter>
</div>
</template>
<script>
import myHeader from '../components/header.vue'
import myFooter from '../components/footer.vue'
export default {
components: { myHeader, myFooter },
data () {
return {
id: this.$route.params.id,
dat: {}
}
},
created () {
this.getData()
},
methods: {
getData () {
this.$axapi.get('topic/' + this.id, null, r => {
this.dat = r.data
})
}
}
}
</script>
这里出过一个错就是,老提示loginname not defined,后来发现是author还没加载就加载了loginname,在p标签里加上v-if后解决问题
运行结果
说明请求成功,具体项目代码在