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

文章寫得比較簡略,有問題歡迎在評論區留言~

相關文章
相關標籤/搜索