Ant Design 4.0更新指南(1)——ProTable

做为React技术栈的坚决拥护者,必定离不开阿里爸爸的大怀抱。做为国内最好用的组件库【之一】的Ant Design迎来个跨版本大更新,年后复工后我在第一时间便进行了尝鲜,恰好公司有老项目重构,在初步了解以后,决定尝试在新项目中使用And Design 4.0进行开发,与之对应的Ant Design Pro也更新到了4.0版本,Ant Design Pro是给予Ant Design的开箱即用中台前端/设计解决方案。简单的说,Ant Dsign是砖头,那Ant Design Pro就是用这些砖头垒起来的框架,你能够基于这个框架来按照你本身的想法从新装修,也能够在不破坏主体结构的状况下拆除部份内容重建。举个例子,对于我来讲,原框架集成的国际化部分是无用的,那我就须要剔除。本系列文章主要针对在项目中使用Ant Design 4.0中遇到的一下值得注意的点~html

本片先来讲一下让我非常喜欢的ProTable这个新组件,让咱们一块儿来看看它到底Pro在哪里。前端

以往,咱们在作列表功能之类,须要重复的去手动的在componentDidMount钩子写请求数据,而后把数据重model中取出来,而后再放到Table组件的dataSource属性中,而后还要处理pageChange事件,而后还要手动的去渲染搜索项,而后就又得本身去引入各类组件,而后又各类堆接节点...这个过程下来,人都要惆怅咯。再加之通常作这种中后台管理系统,相似的功能不少,重复且低效的工做方式简直没法忍受。react

import React, { PureComponent, Fragment } from 'react';
import { connect } from 'dva';
import { Row, Col, Card, Form, Input, Button, DatePicker, Divider, message, Table } from 'antd';
import router from 'umi/router';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import { formatDate, getStartTimeStamp, getEndTimeStamp } from '@/utils/utils';
import styles from './style.less';

const FormItem = Form.Item;
const { RangePicker } = DatePicker;
const getValue = obj =>
  Object.keys(obj)
    .map(key => obj[key])
    .join(',');

/* eslint react/no-multi-comp:0 */
@connect(({ approval, studentManagment, loading }) => ({
  approval,
  studentManagment,
  loading: loading.effects['studentManagment/fetch'],
}))
@Form.create()
class StudentManagement extends PureComponent {
  state = {
    selectedRows: [],
    formValues: {},
  };

  columns = [
    {
      title: '名称',
      dataIndex: 'name',
      render: val => val || '-',
    },
    {
      title: '建立日期',
      dataIndex: 'createTime',
      render: val => val && formatDate(val),
    },    {
      title: '性别',
      dataIndex: 'sex'
    },
    {
      title: '年龄',
      dataIndex: 'age'
    },
    {
      title: '学校',
      dataIndex: 'school'
    },
    {
      title: '年级',
      dataIndex: 'grade'
    },
    {
      title: '操做',
      render: (text, record) => (
        <Fragment> <a onClick={() => router.push({ pathname: '/common/landing-page-management/edit', query: { id: record.id, }, }) } > 编辑 </a> <Divider type="vertical" /> <a onClick={() => this.onCopyLink(record)}>复制连接</a> </Fragment>
      ),
    },
  ];

  componentWillMount() {
    this.getData();
  }

  getData = params => {
    const { dispatch } = this.props;
    dispatch({
      type: 'studentManagment/fetch',
      payload: params,
    });
  };

  onCopyLink = record => {
    const input = document.createElement('input');
    input.value = record.shortUrl;
    document.body.appendChild(input);
    input.select();
    input.setSelectionRange(0, input.value.length);
    document.execCommand('Copy');
    document.body.removeChild(input);
    message.success('复制成功!');
  };

  handleStandardTableChange = (pagination, filtersArg, sorter) => {
    const { formValues } = this.state;

    const filters = Object.keys(filtersArg).reduce((obj, key) => {
      const newObj = { ...obj };
      newObj[key] = getValue(filtersArg[key]);
      return newObj;
    }, {});

    const params = {
      page: pagination.current,
      pageSize: pagination.pageSize,
      ...formValues,
      ...filters,
    };
    if (sorter.field) {
      params.sorter = `${sorter.field}_${sorter.order}`;
    }
    this.getData(params);
  };

  handleFormReset = () => {
    const { form } = this.props;
    form.resetFields();
    this.setState({
      formValues: {},
    });
    this.getData();
  };

  handleSelectRows = rows => {
    this.setState({
      selectedRows: rows,
    });
  };

  handleSearch = e => {
    e.preventDefault();

    const { form } = this.props;

    form.validateFields((err, fieldsValue) => {
      if (err) return;

      const values = {
        name: fieldsValue.name,
        startDate: fieldsValue.date && getStartTimeStamp(fieldsValue.date[0]),
        endDate: fieldsValue.date && getEndTimeStamp(fieldsValue.date[1]),
      };

      this.setState({
        formValues: values,
      });

      this.getData(values);
    });
  };

  renderForm() {
    const {
      form: { getFieldDecorator },
    } = this.props;
    return (
      <Form onSubmit={this.handleSearch} layout="inline"> <Row gutter={{ md: 8, lg: 24, xl: 48 }}> <Col md={8} sm={24}> <FormItem label="名称"> {getFieldDecorator('name')(<Input placeholder="请输入" />)} </FormItem> </Col> <Col md={8} sm={24}> <FormItem label="建立日期"> {getFieldDecorator('date')(<RangePicker style={{ width: '100%' }} />)} </FormItem> </Col> <Col md={8} sm={24}> <Button type="primary" htmlType="submit"> 查询 </Button> <Button style={{ marginLeft: 8 }} onClick={this.handleFormReset}> 重置 </Button> </Col> </Row> <div style={{ overflow: 'hidden' }}> <div style={{ float: 'left', marginBottom: 24 }}> <Button icon="plus" type="primary" onClick={() => router.push({ pathname: '/common/landing-page-management/add' })} > 新增 </Button> </div> </div> </Form>
    );
  }

  render() {
    const {
      studentManagment: { list },
      loading,
    } = this.props;
    const { selectedRows } = this.state;
    return (
      <PageHeaderWrapper> <Card bordered={false}> <div className={styles.tableList}> <div className={styles.tableListForm}>{this.renderForm()}</div> <Table selectedRows={selectedRows} loading={loading} data={list} columns={this.columns} onSelectRow={this.handleSelectRows} onChange={this.handleStandardTableChange} /> </div> </Card> </PageHeaderWrapper>
    );
  }
}

export default StudentManagement;
复制代码

上面是一个用Table来作查询列表功能的一个小demo,大体流程以下:markdown

  • 引入Table组件,编写页面jsx;
  • 编写columns数据;
  • 根据本身的需求编写搜索表单的jsx;
  • 处理查询事件,pageChange事件等

能够发现这实际上是一个重复的工做,大部分状况下只须要按照固定熟悉来写差很少同样的代码就行了。antd

如今,咱们有了ProTable,再来看看怎么作呢~app

import { PlusOutlined } from '@ant-design/icons';
import { Button, Divider } from 'antd';
import React, { Component, Fragment } from 'react';
import router from 'umi/router';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import ProTable from '@ant-design/pro-table';
import { copyString, formatDate, getStartTimeStamp, getEndTimeStamp } from '@/utils/utils';
import { connect } from 'dva';
import { queryRule } from './service';

class StudentManagement extends Component {
  columns = [
    {
      title: '名称',
      dataIndex: 'name',
      ellipsis: true,
    },
    {
      title: '建立日期',
      dataIndex: 'createTime',
      valueType: 'dateRange',
      render: val => val && formatDate(val),
    },
    {
      title: '性别',
      dataIndex: 'sex',
      hideInSearch: true,
    },
    {
      title: '年龄',
      dataIndex: 'age',
      hideInSearch: true,
    },
    {
      title: '学校',
      dataIndex: 'school',
      hideInSearch: true,
    },
    {
      title: '年级',
      dataIndex: 'grade',
      hideInSearch: true,
    },
    {
      title: '操做',
      dataIndex: 'option',
      valueType: 'option',
      render: (_, record) => (
        <Fragment> <a onClick={() => router.push({ pathname: '/public-resource/landing-page-management/edit', query: { id: record.id, }, }) } > 编辑 </a> <Divider type="vertical" /> <a onClick={() => copyString(record.shortUrl)}>复制连接</a> </Fragment>
      ),
    },
  ];

  render() {
    return (
      <PageHeaderWrapper> <ProTable toolBarRender={() => [ <Button type="primary" onClick={() => router.push('/public-resource/landing-page-management/add')} > <PlusOutlined /> 新建 </Button>, ]} rowKey="id" dateFormatter="number" request={params => queryRule({ ...params, current: undefined, startDate: params.createTime && getStartTimeStamp(params.createTime[0]), endDate: params.createTime && getEndTimeStamp(params.createTime[1]), }) } columns={this.columns} /> </PageHeaderWrapper>
    );
  }
}

export default connect(({ studentManagement }) => ({
  studentManagement,
}))(StudentManagement);
复制代码

写完以后最直观的感觉就是代码量足足少了一半!!ProTable将请求数据、处理数据、渲染节点的这个过程封装了起来,使得咱们只须要按照他的约定来进行配置便可完成大部分操做。如今:咱们流程就变成了:框架

  • 引入ProTable组件和请求数据的方法并配置好;
  • 按照ProTable的规则维护columns便可。

在新的ProTable中,与以往不一样的是,咱们须要维护的columns中新增了一个valueType属性,按照约定值,ProTable将根据这个属性来渲染表单项和表头。剩下的Search事件、Reset事件、pageChange事件等等等等...ProTable都会帮你作好。less

ProTable大法好,上车保平安。学会用ProTable,今后列表一把梭~ide

官方文档地址:protable.ant.design/oop

文章写得比较简略,有问题欢迎在评论区留言~

相关文章
相关标签/搜索