IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 一种列表全字段排序功能方案 -> 正文阅读

[JavaScript知识库]一种列表全字段排序功能方案

概述

网站开发中,很常见的一个需求:要对列表页的全部(或大多数)字段进行排序。

实现

先给出实现好的效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

前端

注:主要技术栈为antd,TypeScript。

const columns = [
  {
    title: '名称',
    dataIndex: 'name',
    sorter: true,
    render: (text: string, record: any) => (
      <div style={{maxWidth: 200,lineHeight: 1.2}}>{record?.name}</div>
    ),
  },
]

sorter指定该字段是否需要排序功能,两种情况下可以设置为sorter: false

  1. 对于跨表Join的字段,有些是无法排序;
  2. 无需排序的列(其实也不叫字段),如操作列。

另外,有些列会有render的特殊需求,在加排序功能之前,并没有配置dataIndex: 'name'。但是在引入排序功能后,必须指定该字段,下面代码里面的sorter.field即依赖于此字段,否则sorter.fieldundefined

列表组件:

<Vi_Table
  loading={dataLoading}
  rowKey={(record: any) => record.id}
  columns={columns}
  dataSource={autoJobListData.list}
  pagination={{
    ...pagination,
    position: ['bottomCenter'],
    total: autoJobListData.total,
    showSizeChanger: true,
    showQuickJumper: true,
    showTotal: (total: any) => (`${total}`),
  }}
  onChange={handleTableChange}
/>

列表onChange方法:

const handleTableChange = (pagination: any, filters: any, sorter: any) => {
    if (sorter && sorter.field && sorter.order) {
        fetchDataWithParams({
            ...form.getFieldsValue(),
            ...pagination,
            sortField: sorter.field,
            sortOrder: sorter.order === 'descend' ? 'desc' : 'asc'
        });
    } else {
        fetchDataWithParams({
            ...form.getFieldsValue(),
            ...pagination,
            sortField: undefined,
            sortOrder: undefined
        });
    }
};

后端

Controller接口

@RequestMapping("/list")
public String autoJobList(@RequestBody JSONObject jsonObject) {
    return autoWordConfigService.autoJobList(jsonObject);
}

以JSONObject(或Map)来接收若干参数。

Service方法:

public String autoJobList(JSONObject jsonObject) {
    PageHelper.startPage(jsonObject.getInteger("pageNo"), jsonObject.getInteger("pageSize"));
    if (StringUtils.isNotBlank(jsonObject.getString("sortField"))) {
        jsonObject.put("sortField", StringUtil.camelCaseToUnderscore(jsonObject.getString("sortField")));
    }
    List<AutoWordConfigWithBlobs> list = autoWordConfigMapper.autoJobList(jsonObject);
    PageInfo<AutoWordConfigWithBlobs> pageInfo = new PageInfo<>(list);
    return JSONObject.toJSONString(ServiceUtil.returnSuccessData(pageInfo));
}

主要就是分页功能,以及将驼峰命名转换为下划线命名,目地是对数据表里面下划线命名的字段进行排序。

Mapper接口:

<select id="autoJobList" resultType="com.xy.cloudiview.common.po.AutoWordConfigWithBlobs"
        parameterType="java.util.Map">
    select ac.id
    FROM auto_word_config ac LEFT JOIN category dc ON ac.category_id = dc.category_id
    LEFT JOIN `user` duo on duo.user_id= ac.owner_id
    WHERE ac.isactive = 1 AND dc.isactive = 1
    <if test="sortOrder == null or sortOrder == ''">
        ORDER BY ac.update_time DESC
    </if>
    <if test="sortField != null and sortOrder != null">
        ORDER BY
        <choose>
            <when test="sortField == 'owner_name' ">
                duo.user_name
            </when>
            <when test="sortField == 'category_name'">
                dc.${sortField}
            </when>
            <otherwise>
                ac.${sortField}
            </otherwise>
        </choose>
        <if test="sortOrder == 'asc'">
            ASC
        </if>
        <if test="sortOrder == 'desc'">
            DESC
        </if>
    </if>
</select>

逻辑:

  1. 如果没有排序,则默认以更新时间降序获取列表;否则就以前端指定的字段来排序;
  2. 跨表join时,需要通过choose...when...otherwise来选择哪个表的字段来进行排序;
  3. 不能使用#{sortField},必须使用${sortField}。因为前者为了防止SQL注入,会自动加单引号'',导致拼接的SQL执行异常。

工具类方法:

/**
 * 驼峰转下划线
 *
 * @param camel camel
 * @return Underscore
 */
public static String camelCaseToUnderscore(String camel) {
    StringBuilder underscore;
    underscore = new StringBuilder(String.valueOf(Character.toLowerCase(camel.charAt(0))));
    for (int i = 1; i < camel.length(); i++) {
        underscore.append(Character.isLowerCase(camel.charAt(i)) ? String.valueOf(camel.charAt(i))
                : "_" + Character.toLowerCase(camel.charAt(i)));
    }
    return underscore.toString();
}

拓展

局限

只能指定一个排序字段。

优化

上面的代码,可以进一步优化:
前端传参:sortOrder: sorter.order === 'descend' ? 'DESC' : 'ASC'
后端那一大坨代码:

<if test="sortOrder == 'asc'">
    ASC
</if>
<if test="sortOrder == 'desc'">
    DESC
</if>

则可以替换为:${sortOrder}

规范

上面这个方案,建立在一个开发规范上,即数据表的定义为下划线命名,后端POJO定义为驼峰命名,返回给前端的是驼峰命名,并且驼峰命名通过工具类方法可以转化为下划线。

如果数据表字段定义为board_id,但是返回给前端的字段确实id,此时如果以id来排序,需要映射为boardId,无论是前端还是后端,都需要加一层繁琐的映射:

if (sorter && sorter.field && sorter.order) {
  if (sorter.field === 'id') {
      sorter.field = 'boardId'
  }
  if (sorter.field === 'name') {
      sorter.field = 'boardName'
  }
  fetchDataWithParams({
      ...form.getFieldsValue(),
      ...pagination,
      sortField: sorter.field,
      sortOrder: sorter.order === 'descend' ? 'desc' : 'asc'
  });
}

所以开发规范很重要!!

参考

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-11 15:37:53  更:2021-12-11 15:40:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:57:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码