异步查询数据,自然是通过ajax查询,Vue官方推荐的ajax请求框架叫做:axios.
文章: https://blog.lee-cloud.xyz/post/1/Axios-zhong-wen-wen-dang
demo:
axios的Get请求语法:
axios.get("/item/category/list?pid=0") // 请求路径和请求参数拼接
.then(function(resp){
// 成功回调函数
})
.catch(function(){
// 失败回调函数
})
// 参数较多时,可以通过params来传递参数
axios.get("/item/category/list", {
params:{
pid:0
}
})
.then(function(resp){})// 成功时的回调
.catch(function(error){})// 失败时的回调
axios的POST请求语法:
axios.post("/user",{
name:"Jack",
age:21
})
.then(function(resp){})
.catch(function(error){})
注意:
- GET请求那样定义一个对象,在对象的params参数中传参。
- post()方法的第二个参数对象,就是将来要传递的参数 。
- PUT和DELETE请求与POST请求类似
axios的全局配置
axios进行了简单的封装,在src下的http.js中:
http.js中对axios进行了一些默认配置:
import Vue from 'vue'
import axios from 'axios'
import config from './config'
// config中定义的基础路径是:http://api.leyou.com/api
axios.defaults.baseURL = config.api; // 设置axios的基础请求路径
axios.defaults.timeout = 2000; // 设置axios的请求时间
Vue.prototype.$http = axios;// 将axios赋值给Vue原型的$http属性,这样所有vue实例都可使用该对象
http.js对axios进行了全局配置:
baseURL=config.api,即http://api.leyou.com/api。因此以后所有用axios发起的请求,都会以这个地址作为前缀。
通过Vue.property.$http = axios,将axios赋值给了 Vue原型中的$http。这样以后所有的Vue实例都可以访问到$http,也就是访问到了axios了。
异步加载品牌数据
请求参数:
page:当前页,int
rows:每页大小,int
sortBy:排序字段,String
desc:是否为降序,boolean
key:搜索关键词,String
而页面中分页信息应该是在pagination对象中,我们通过浏览器工具,查看pagination中有哪些属性:
页面数据:
descending:是否是降序,对应请求参数的desc
page:当前页,对应参数的page
rowsPerpage:每页大小,对应参数中的rows
sortBy:排序字段,对应参数的sortBy
通过v-model与输入框绑定的属性:search。
发起请求
this.$http.get("/item/brand/page",{
params:{
key: this.search, // 搜索条件
page: this.pagination.page,// 当前页
rows: this.pagination.rowsPerPage,// 每页大小
sortBy: this.pagination.sortBy,// 排序字段
desc: this.pagination.descending// 是否降序
}
}).then(resp => { // 这里使用箭头函数
// 将得到的数据赋值给本地属性
this.brands = resp.data.items;
this.totalBrands = resp.data.total;
// 完成赋值后,把加载状态赋值为false
this.loading = false;
})
请求参数格式错误(表单提交)
axios处理请求体的原则会根据请求数据的格式来定:
如果请求体是对象:会转为json发送
如果请求体是String:会作为普通表单请求发送,但需要我们自己保证String的格式是键值对。
如:name=jack&age=12(表单提交的格式)
QS工具:(Query String,请求参数字符串)
npm install qs --save
实现 JS的Object与QueryString的转换。
有3个方法:
这里我们要使用的方法是stringify,它可以把Object转为QueryString。
1.3.3.解决问题
修改页面,对参数处理后发送:
然后再次发起请求:
完成分页和过滤
4.6.1.分页
现在我们实现了页面加载时的第一次查询,你会发现你点击分页或搜索不会发起新的请求,怎么办?
虽然点击分页,不会发起请求,但是通过浏览器工具查看,会发现pagination对象的属性一直在变化:
我们可以利用Vue的监视功能:watch,当pagination发生改变时,会调用我们的回调函数,我们在回调函数中进行数据的查询即可!
具体实现:
4.6.2.过滤
分页实现了,过滤也很好实现了。过滤字段对应的是search属性,我们只要监视这个属性即可:
完整代码
<template>
<v-card>
<v-card-title>
<v-btn color="primary" @click="addBrand">新增品牌</v-btn>
<!--搜索框,与search属性关联-->
<v-spacer/>
<v-text-field label="输入关键字搜索" v-model.lazy="search" append-icon="search" hide-details/>
</v-card-title>
<v-divider/>
<v-data-table
:headers="headers"
:items="brands"
:search="search"
:pagination.sync="pagination"
:total-items="totalBrands"
:loading="loading"
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td>{{ props.item.id }}</td>
<td class="text-xs-center">{{ props.item.name }}</td>
<td class="text-xs-center"><img :src="props.item.image"></td>
<td class="text-xs-center">{{ props.item.letter }}</td>
<td class="justify-center layout">
<v-btn color="info">编辑</v-btn>
<v-btn color="warning">删除</v-btn>
</td>
</template>
</v-data-table>
</v-card>
</template>
<script>
import MyBrandForm from './MyBrandForm'
export default {
name: "my-brand",
data() {
return {
search: '', // 搜索过滤字段
totalBrands: 0, // 总条数
brands: [], // 当前页品牌数据
loading: true, // 是否在加载中
pagination: {}, // 分页信息
headers: [
{text: 'id', align: 'center', value: 'id'},
{text: '名称', align: 'center', sortable: false, value: 'name'},
{text: 'LOGO', align: 'center', sortable: false, value: 'image'},
{text: '首字母', align: 'center', value: 'letter', sortable: true,},
{text: '操作', align: 'center', value: 'id', sortable: false}
]
}
},
mounted() { // 渲染后执行
// 查询数据
this.getDataFromServer();
},
watch: {
pagination: { // 监视pagination属性的变化
deep: true, // deep为true,会监视pagination的属性及属性中的对象属性变化
handler() {
// 变化后的回调函数,这里我们再次调用getDataFromServer即可
this.getDataFromServer();
}
},
search: { // 监视搜索字段
handler() {
this.getDataFromServer();
}
}
},
methods: {
getDataFromServer() { // 从服务的加载数的方法。
// 发起请求
this.$http.get("/item/brand/page", {
params: {
key: this.search, // 搜索条件
page: this.pagination.page,// 当前页
rows: this.pagination.rowsPerPage,// 每页大小
sortBy: this.pagination.sortBy,// 排序字段
desc: this.pagination.descending// 是否降序
}
}).then(resp => { // 这里使用箭头函数
this.brands = resp.data.items;
this.totalBrands = resp.data.total;
// 完成赋值后,把加载状态赋值为false
this.loading = false;
})
}
}
}
</script>
<style scoped>
</style>