数据代理

在日常开发中,列表数据的分页查询是最为常见的场景,本章的目的是实现一个通用的请求数据代理,减少代码量,提高效率。 最终实现

本章目标

开发无须关心分页查询,条件查询等代码逻辑,只需要配置即可快速实现列表数据的分页查询功能。

例:

<template>
    <div>
        <div>
            <!-- 省略查询html代码 -->
        </div>
        <el-table
            :data="tableList.data"
        >
            <!-- 省略代码 -->
        </el-table>
        <el-pagination
            @size-change="onSizeChange"
            @current-change="onCurrentChange"
            :current-page="tableList.pagination.curr"
            :page-sizes="[5, 10, 20 ,30]"
            :page-size="tableList.pagination.limit"
            :total="tableList.pagination.total"
            layout="total, sizes, prev, pager, next, jumper"
        ></el-pagination>
    </div>
</template>
<script lang='ts'>
import { Component, Vue } from "vue-property-decorator";
import { mixinDataStore } from "@/mixin/view/Store";
import { Action } from "vuex-class";

@Component({
    name: "GridDemo",
    mixins: [mixinDataStore]
})
export default class GridDemo extends Vue {
    // 定义在vuex中的请求数据函数,只要返回的是Promise类型即可
    @Action("list") gridList: any;
    // 预留配置-列表配置
    // 列表代理对象
    tableList: any = {
        // 列表数据源
        data: [],
        // 代理配置
        proxy: {
            // 请求数据函数
            requestFun: this.gridList,
            // 分页每页显示条数字段名称,默认为limit,此参数传递到服务端
            limitParam: "pageSize",
            // 分页页码字段名称,默认为page,此参数传递到服务端
            pageParam: "current",
            // 初始化后自动加载数据
            autoLoad: true,
            // 读取数据相关配置
            reader: {
                // 数据根节点
                rootProperty: "data.data.records",
                successProperty: "data.code",
                totalProperty: "data.data.total",
                messageProperty: "data.data.msg"
            }
        }
    };
}
</script>

具体实现

扩展模块结构设计

挂载代理

如上述代码所示我们通过proxy.init(this.tableList);将相应的函数挂在到了tableList上面,那么如何实现呢。

例:

列表数据请求场景一般分为移动端与web端,而这两者对数据结果集的处理逻辑是不一样的,所以这里我们可以把移动端与web端分成两个类,通过代理配置来挂在对应的类。

例:

classic类

modern类

预留扩展

以上代码能够覆盖大部分场景,并不能覆盖全部场景,所以我们需要预留出可扩展部分,将挂载代理中的类放置于promise文件夹中,我们再实现一个代理父类

整体结构

在代码实现过程中,我们会封装一些公用函数,那么创建一个帮助类是一个很好的选择

例:

如此,整个数据代理模块目录结构如下

avatar

填充代码

入口模块

代理可用配置

  1. type

    为了方便扩展,我们需要一个type配置,用来确定代理类型,默认为经典代理即promise.classic

  2. 分页配置

    为了处理分页等逻辑需要以下配置 1. requestFun -> 请求数据函数 1. pageSize -> 每次加载几条数据,默认为10 1. page -> 当前页码,默认为1 1. limitParam -> 分页每页显示条数字段名称,默认为limit,此参数传递到请求数据函数 1. pageParam -> 分页页码字段名称,默认为page,此参数传递到请求数据函数 1. paginationParam -> 数据源对象接收分页配置节点名称,默认为pagination

  3. defaultParams

    默认参数,默认参数会被相同名称新参数覆盖

  4. autoLoad

    初始化成功后是否自动调用load函数

  5. reader

    读取数据相关配置 1. reader.rootProperty -> 数据根节点名称 1. reader.successProperty -> 判断请求是否成功的节点名称 1. reader.totalProperty -> 数据总数节点名称 1. reader.messageProperty -> 请求失败后失败消息节点名称

  6. 扩展配置

    预留出一些扩展函数,用来处理一些额外的需求 1. disposeItem -> 处理单个数据对象的函数

数据源可用配置

  1. 扩展配置

    预留出一些扩展函数,用来处理一些额外的需求 1. failure -> 请求失败后执行函数 1. writerTransform -> 请求数据前处理请求参数函数 1. readerTransform -> 请求数据成功后处理数据结果函数

    函数

    入口模块我们可以放一些通用逻辑函数,我们可以在里面实现failure、writerTransform扩展配置。

最终代码如下:

promise代理入口模块

函数

不管是移动端还是web端,读取数据的逻辑函数应该是通用的,我们可以在里面实现disposeItem、readerTransform扩展配置。

最终代码如下:

请求数据的函数与返回的数据需要遵循以下规则

  1. 此帮助类只是一个代理类,具体分页查询函数还是需要axios等扩展来实现,但是因为设计时考虑了扩展性,可以自定义一些扩展来实现请求数据的功能

  2. 返回数据必须是标准json格式数据,并且有以下字段,对应字段名称可以在reader配置中灵活配置,如果返回数据不标准可以用readerTransform函数处理成表格格式

    1. success -> 用于判断请求是否成功

    2. data -> 最终数据结果集

    3. total -> 满足当前条件的数据总数,用于分页

    4. message -> 用于请求失败消息提示

假如后端返回数据格式如下,使用axios请求数据并不做任何处理

代理中reader配置如下即可

promise.classic代理

应该有一个基础函数,然后再此基础函数的基础上封装出相应的扩展函数 最终代码如下

promise.modern代理

待实现,预留的移动端代理

使用时二次扩展

将以上模块发布为npm包,可以通过npm install ux-data-proxy命令直接引入。

一般来说后端返回的数据格式是固定的,请求参数也是固定规则,在实际使用中,我们可以自定义一个帮助类来使用,具体代码如下:

在实际使用场景引入这个类即可,使用方式不用改变

mixin类

大多数情况下,分页查询逻辑都是固定的,所以我们可以封装一个mixin类,在估计视图中直接引入这个mixin即可 代码如下:

结语

  1. 移动端代理并未实现,你想好怎么实现了吗?

  2. 假如我们需要对本地数据进行分页查询,并且也分区分web端与移动端,你应该怎么去实现这个扩展

  3. 你是否尝试封装一个查询组件,这个组件支持校验,条件级联等常用功能呢,你要如何去实现才能保证它具有通用性与可扩展性呢

  4. 你是否尝试封装一个列表组件?也许用现成的第三方组件是一个更好的选择哦。

  5. 你是否尝试对css进行封装,定制一个通用场景呢?

最后更新于

这有帮助吗?