AlienGao's blog AlienGao's blog
首页
  • JavaScript
  • Antd组件
  • 学习笔记

    • 《ES6 教程》笔记
  • 贪心
  • 广度优先/深度优先
  • 位运算
  • 技术文档
  • GitHub技巧
面试
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

AlienGao

首页
  • JavaScript
  • Antd组件
  • 学习笔记

    • 《ES6 教程》笔记
  • 贪心
  • 广度优先/深度优先
  • 位运算
  • 技术文档
  • GitHub技巧
面试
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Table再封装
  • DatePicker再封装
  • 筛选组件
  • Antd组件
AlienGao
2021-08-14

Table再封装

背景介绍: 业务需要根据后端提供的 JSON 数据渲染报警报表,包括表格的表头,表格数据,表头的模糊筛选(分两种:1 种是输入框模糊查询,另一种是默认值查询。)

先上代码:

frontend/webapp/src/components/Antdd/Table.js

import { useState, useEffect, useRef } from "react";
import { Table, Input } from "antd";
import { SearchOutlined } from "@ant-design/icons";

const Tabled = (props) => {
  const [fixedColumns, setFixedColumns] = useState([]);
  const inputEl = useRef(null);
  /* 
    设置工单编号可筛选
  */
  const getColumnSearchProps = (dataIndex) => ({
    filterDropdown: ({
      setSelectedKeys,
      selectedKeys,
      confirm,
      clearFilters,
    }) => (
      <div style={{ 
        padding: 8,
        boxShadow: '0 3px 6px -4px rgb(0 0 0 / 12%), 0 6px 16px 0 rgb(0 0 0 / 8%), 0 9px 28px 8px rgb(0 0 0 / 5%)',
        position: 'absolute',
        width: '244px',
        height: '56px',
        background: '#fff',
        left: '-50px',
        top: '-4px'
      }}>
        <Input
          ref={node => {
            inputEl.current = node
          }}
          allowClear
          value={selectedKeys[0]}
          onChange={(e) => {
            setSelectedKeys(e.target.value ? [e.target.value] : []);
            // 报表页面删除筛选项 再次展示下拉框没有值
            if (props.type === 'statisitcs') {
              if (!e.target.value) {
                handleSearch([], confirm, dataIndex);
              }
            }
          }}
          onPressEnter={() => handleSearch(selectedKeys, confirm, dataIndex)}
          style={{ marginBottom: 8, display: "block" }}
          addonAfter={
            <SearchOutlined
              onClick={() => {
                handleSearch(selectedKeys, confirm, dataIndex);
              }}
            />
          }
        />
      </div>
    ),
    onFilterDropdownVisibleChange: visible => {
      if (visible) {
        setTimeout(() => inputEl.current.select(), 100);
      }
    },
    filterIcon: () => (
      <SearchOutlined
        style={{ color: props.filters[dataIndex] ? "#1890ff" : undefined }}
      />
    ),
  });

  const handleSearch = (selectedKeys, confirm, dataIndex) => {
    confirm();
    const obj = {};
    obj[dataIndex] = selectedKeys[0];
    props.setFilters({
      ...props.filters,
      page_no: 1,
      ...obj,
    });
  };

  useEffect(() => {
    var result = [];
    if (props.sortArr) {
      result = props.fixedColumns.map((c) => {
        if (props.sortArr.indexOf(c.key) > -1) {
          return {
            ...c,
            width: 180,
            ...getColumnSearchProps(c.key)
          }
        }
        return c;
      });
    }
    if (props.filteredArr && props.filteredArr.length > 0) {
      result = result.map((r) => {
        const obj = props.filteredArr.find((f) => f.key === r.key);
        if (obj) {
          return {
            ...r,
            filters: obj.value,
            filterMultiple: obj.filterMultiple,
            filteredValue: props.filters[obj.key] || null,
          };
        }
        return r;
      });
    }
    if (result.length > 0) {
      setFixedColumns(result);
    } else {
      setFixedColumns(props.fixedColumns);
    }
    // eslint-disable-next-line
  }, [props.sortArr, props.filteredArr, props.total, props.fixedColumns])
  
  useEffect(() => {
    // antd Table 在筛选后内容高度小于一屏高度会出现两条滚动条
    setTimeout(() => {
      if (document.getElementById("BackTopMark")) {
        document.getElementById("BackTopMark").scrollTop += 1;
      }
    }, 300);
  }, [props.dataSource]);

  const handleTableChange = (pagination, filters, sorter) => {
    const obj = {}
    let hasChange = false
    for (let key in filters) {
      // 筛选有值
      if (filters[key]) {
        obj[key] = filters[key]
      } else {
        // 有旧值
        if (props.filters[key]) {
          obj[key] = undefined
        }
      }
      if (filters[key] !== props.filters[key]) {
        if (!props.filters[key] && !filters[key]) {
          hasChange = false
        } else {
          hasChange = true
        }
      }
    }
    props.setFilters({
      ...props.filters,
      ...obj,
      page_no: pagination.pageSize !== props.filters.page_size || hasChange ? 1 : pagination.current,
      page_size: pagination.pageSize,
    })
  };

  return (
    <Table
      columns={fixedColumns}
      {...props}
      scroll={{ x: 1300 }}
      sticky={{
        getContainer: () => document.getElementById("BackTopMark"),
      }}
      getPopupContainer={() => document.getElementById("BackTopMark")}
      pagination={{
        total: props.total,
        showSizeChanger: true,
        pageSizeOptions: [10, 20, 50, 100],
        pageSize: props.filters.page_size,
        current: props.filters.page_no,
        showTotal: (total, range) =>
          `第${range[0]}-${range[1]}行,共${total}行`,
      }}
      onChange={handleTableChange}
    />
  );
};

Tabled.propTypes = Table.propTypes;

Tabled.defaultProps = {
  ...Table.defaultProps,
};

export default Tabled;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

使用例子:

<Table
  rowKey="id"
  fixedColumns={columns}
  dataSource={dataSource}
  sortArr={sortArr}
  filteredArr={filteredArr}
  setFilters={setFilters}
  filters={filters}
  total={total}
/>
1
2
3
4
5
6
7
8
9
10

从使用例子中可以看到 Table 组件接受表头,表格数据,筛选数组(分为模糊查询和固定筛选项),filters 为所有筛选字段包括默认筛选字段(比如页面,每页展示条数)。

通过将表格功能的封装,可以只需要在父组件中添加配置就能完成所需功能,极大的提高了开发效率并且需要添加新的功能只需要修改一个文件就能全局应用。

编辑 (opens new window)
#组件
上次更新: 2021/08/14, 19:30:57
DatePicker再封装

DatePicker再封装→

最近更新
01
Promise
08-18
02
Vue查漏补缺
08-16
03
筛选组件
08-14
更多文章>
Theme by Vdoing | Copyright © 2021-2021 AlienGao | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×