美文网首页
Vue实战(三) - 实战项目(中) - 深入组件/内置函数/R

Vue实战(三) - 实战项目(中) - 深入组件/内置函数/R

作者: ElliotG | 来源:发表于2021-05-09 20:42 被阅读0次

    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>
    

    效果图如下:


    image.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>
    

    效果图如下:

    image.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映射。

    相关文章

      网友评论

          本文标题:Vue实战(三) - 实战项目(中) - 深入组件/内置函数/R

          本文链接:https://www.haomeiwen.com/subject/vjjvdltx.html