1. 自定义分页组件
1-1) 准备分页数据(通过全局状态管理)
修改一下src/store文件夹下的index.js以支持分页。
代码如下:
...
export default new Vuex.Store({
strict: true,
state: {
products: testData,
productsTotal: testData.length,
currentPage: 1,
pageSize: 4
},
getters: {
processedProducts: state => {
let index = (state.currentPage -1) * state.pageSize;
return state.products.slice(index, index + state.pageSize);
},
pageCount: state => Math.ceil(state.productsTotal / state.pageSize)
},
mutations: {
setCurrentPage(state, page) {
state.currentPage = page;
},
setPageSize(state, size) {
state.pageSize = size;
state.currentPage = 1;
}
}
})
代码解释:
I. state(状态)部分:
我们看到,在state中我们添加了几个状态来支持分页。
除了原来的products代表所有数据以外,
我们添加了下面3项:
productsTotal - 记录总数
currentPage - 当前页
pageSize - 每页记录数
--------------------------------------------------------------
II. getters部分:
processedProducts - 当前页所有的记录
pageCount - 总共有多少页
--------------------------------------------------------------
III. mutations部分:
mutations - 定义了可以改变state中多个状态的方法
之前我们提到过, 改变store中状态的唯一途径就是显式地提交mutation。
setCurrentPage - 改变state中的currentPage属性
setPageSize - 改变state中的pageSize属性,同时重置currentPage属性
- 重要点
a. 通过mutations来改变state状态
b. 通过getters来对外暴露状态的处理值
1-2) 新建分页组件
PageControls.vue
<template>
<div v-if="pageCount > 1" class="text-right">
<div class="btn-group mx-2">
<button v-for="i in pageNumbers" v-bind:key="I"
class="btn btn-secpmdary"
v-bind:class="{ 'btn-primary': i == currentPage }">
{{ I }}
</button>
</div>
</div>
</template>
<script>
import { mapState, mapGetters } from "vuex";
export default {
computed: {
...mapState(["currentPage"]),
...mapGetters(["pageCount"]),
pageNumbers() {
return [...Array(this.pageCount + 1).keys()].slice(1);
}
}
}
</script>
代码解释:
关键词 | 详细描述 |
---|---|
mapState | 映射之前state中的currentPage(当前页)属性。 |
mapGetters | 映射之前getters中的pageCount(总页数)属性。 |
pageNumbers | 自定义计算属性(computed)方法用于显示第几页。 |
1-3) 列表组件中引用分页组件
修改ProductList.vue如下:
<template>
<div>
<div v-for="p in products" ...>
...
</div>
<page-controls />
</div>
</template>
<script>
import { mapGetters } from "vuex";
import PageControls from "./PageControls";
export default {
components: { PageControls },
computed: {
...mapGetters({ products: "processedProducts" })
},
...
}
</script>
效果图如下:
![](https://img.haomeiwen.com/i12347236/27cdbdedb92ddfb8.png)
1-4) 分页按钮事件
代码如下
<template>
<div class="col form-group">
<select class="form-control" v-on:change="changePageSize">
<option value="4">4 per page</option>
<option value="8">8 per page</option>
<option value="12">12 per page</option>
</select>
</div>
<div>
...
<button v-for="i in pageNumbers" v-bind:key="I"
...
v-on:click="setCurrentPage(i)">
...
</button>
</div>
</template>
<script>
import { mapState, mapGetters, mapMutations } from "vuex";
export default {
...
methods: {
...mapMutations(["setCurrentPage", "setPageSize"]),
changePageSize($event) {
this.setPageSize(Number($event.target.value));
}
}
}
</script>
效果图如下:
![](https://img.haomeiwen.com/i12347236/1d69657b1fed214f.png)
- 重要点
store中的mutations是不能直接在组件中调用的,要通过mapMutations函数来进行映射。
2. 调用REST服务
2-1) 修改store, 增加axios库支持和actions
代码如下
...
import Axios from "axios";
Vue.use(Vuex);
const baseUrl = "http://localhost:3500";
const productsUrl = `${baseUrl}/products`;
const categoriesUrl = `${baseUrl}/categories`;
export default new Vuex.Store({
strict: true,
state: {
...
categoriesData: []
},
getters: {
...
categories: state => ["All", ...state.categoriesData]
},
mutations: {
...
setData(state, data) {
state.products = data.pdata;
state.productsTotal = data.pdata.length;
state.categoriesData = data.cdata.sort();
}
},
actions: {
async getData(context) {
let pdata = (await Axios.get(productsUrl)).data;
let cdata = (await Axios.get(categoriesUrl)).data;
context.commit("setData", { pdata, cdata } );
}
}
})
代码解释:
1. Axios库发起get请求获取数据。
2. async 和 await关键字配合使用,async修饰方法表示该方法异步,await等待异步任务结束后获取数据。
3. actions中的getData异步方法在获取到请求数据后,调用mutations中的方法来修改状态中的数据。
- 重要点
a. mutations中必须都是同步函数,不能存在异步调用。
b. action可以包含异步操作,用于放置异步方法(eg: 网络请求)。
c. actions通过context对象来访问data store的一些功能(eg: 提交mutations修改状态)。
2-2) 组件调用异步的action方法
代码如下
App.vue
...
<script>
...
import { mapActions } from "vuex";
export default {
...
methods: {
...mapActions(["getData"])
},
created() {
this.getData();
}
}
</script>
代码解释:
1. mapActions映射之前我们在store中定义的异步action - getData, 用于请求数据并且修改数据状态。
2. created方法在组件创建时调用。
- 重要点
组件不能直接调用action方法,需要通过mapActions映射。
网友评论