• 【共享单车】—— React后台管理系统开发手记:AntD Table基础表格


    前言:以下内容基于React全家桶+AntD实战课程的学习实践过程记录。最终成果github地址:https://github.com/66Web/react-antd-manager,欢迎star。


     一、基础表格

    • Table组件基础Api
    1. bordered属性:是否展示外边框和列边框
    2. columns属性:表格列的配置描述(即表头
    3. dataSource属性:数据数组
    4. pagination属性:分页器,设为 false 时不展示和进行分页
       <Card title="基础表格">
                <Table 
                         bordered
                         columns={columns}
                         dataSource={this.state.dataSource}
                         pagination={false}
                  />
      </Card>
      
    • Table基本用法

    1. render()中:定义columns表头配置信息数组

       const columns = [
                   {
                       title: 'id',   //表头标题
                       dataIndex: 'id' //数据源
                   },
                   {
                       title: '用户名',
                       dataIndex: 'userName'
                   },
                   {
                      title: '性别',
                      dataIndex: 'sex',
                      render(sex){
                          return sex === 1 ? '男' : '女'
                      }
                   },
                   {
                      title: '状态',
                      dataIndex: 'state',
                      render(state){
                          let config = {
                              '1': '咸鱼一条',
                              '2': '人民公仆',
                              '3': '医院护士',
                              '4': '科技公司FE',
                              '5': '创业者'
                          }
                          return config[state]
                      }
                   },
                   {
                      title: '爱好',
                      dataIndex: 'interest',
                      render(abc){
                          let config = {
                              '1': '游泳',
                              '2': '打篮球',
                              '3': '踢足球',
                              '4': '跑步',
                              '5': '爬山',
                              '6': '骑行',
                              '7': '桌球',
                              '8': '麦霸'
                          }
                          return config[abc]
                      }
                   },
                   {
                      title: '生日',
                      dataIndex: 'birthday'
                   },
                   {
                      title: '地址',
                      dataIndex: 'address'
                   },
                   {
                      title: '早起时间',
                      dataIndex: 'time'
                   }       
              ]
    2. componentDidMount()中:指定表格的数据源 dataSource 为一个数组
      const dataSource = [   //数据源
                  {
                      id: '0',
                      userName: 'Elena',
                      sex: '1',
                      state: '1',
                      interest: '1',
                      birthday: '2019-01-01',
                      address: '西虹市海淀区桃花公园',
                      time: '07:00'
                  },
                  {
                      id: '1',
                      userName: 'Mary',
                      sex: '1',
                      state: '2',
                      interest: '3',
                      birthday: '2019-01-01',
                      address: '西虹市海淀区桃花公园',
                      time: '07:00'
                  },
                  {
                      id: '2',
                      userName: 'Tom',
                      sex: '2',
                      state: '3',
                      interest: '4',
                      birthday: '2019-01-01',
                      address: '西虹市海淀区桃花公园',
                      time: '07:00'
                  }
              ]  
    3. 报错:原因是数据需要指定唯一key值;使用 map 循环遍历可以快速添加key值

        

    4. 注意:定义好数据源后,必须通过this.setStatedataSource添加到state

      state={}
      
      componentDidMount(){
          const dataSource= [……],
          dataSource.map((item, index) => {
              item.key = index;
          })
          this.setState({
              dataSource
          })
      }
      

           

    二、动态数据渲染表格

    • 动态渲染数据
    1. 在线工具模拟数据:Easy Mock用法及Mock.js规范 

    2. 生成数据

    3. src->axios->index.js:定义ajax方法,封装axios异步获取Easy Mock项目虚拟数据的过程【项目工程化】

      import axios from 'axios'
      import { Modal } from 'antd';
      
      export default class Axios{
            ……
            static ajax(options){
               let baseApi = 'https://www.easy-mock.com/mock/5c2c7c1b580d6209d1e2aa88/mockapi'
               return new Promise((resolve,reject) => {
                    axios({
                          url: options.url,
                          method:'get',
                          baseURL: baseApi,
                          timeout: 5000,
                          params: (options.data && options.data.params) || ''
                    }).then((response)=>{
                      if(response.status === 200){
                            let res = response.data;
                            if(res.code === 0){
                                resolve(res);
                            }else{
                                Modal.info({
                                    title: '提示',
                                    content: res.msg
                                })
                            }   
                      }else{
                            reject(response.data)
                      }
                    })
               });
           }
      }
      

      注意:根据返回的response获取数据信息时,要按照Easy Mock中定义的数据结构而定!!!

    4. baseTable.js中:定义request方法,调用axios动态获取Mock数据

      import axios from './../../axios/index'
      
      state = {
           dataSource2: []
      }
      params = {
            page: 1
      }
      
      //动态获取mock数据
      request = () => {
              let _this = this;
              axios.ajax({
                  url: '/table/list',
                  data:{
                      params:{
                          page: this.params.page
                      }
                  }
              }).then((res) => {
                  if(res.code === 0){
                     res.list.map((item, index) => {
                         item.key = index
                     })
                     this.setState({
                         dataSource2: res.list
                     })
                  }
              })
       }
    5. Table组件中:指定数据源为动态获取到的dataSource2

      <Card title="Mock-动态数据渲染表格" style={{margin: '10px 0'}}>
            <Table 
                 bordered
                 columns={columns}
                 dataSource={this.state.dataSource2}
                 pagination={false}
            />
      </Card>

      

    三、表格单选

    • rowSelection属性:列表项是否可选择,对象
    • 配置项:
    1. type:单选/多选
    2. selectedRowKeys:指定选中项的key数组,需要和onChange进行配合(单选,仅onRow事件即可)
      const selectedRowKeys = this.state.selectedRowKeys;
      const rowSelection = {
            type: 'radio',
            selectedRowKeys
      }
      
    • onRow事件:控制点击某一行,设置行属性

       <Card title="Mock-单选" style={{margin: '10px 0'}}>
            <Table 
                  bordered
                  rowSelection={rowSelection}
                  onRow={(record, index) => {
                        return {
                             onClick: () => { 
                                  this.onRowClick(record, index)
                             }  //点击行
                        }
                  }}
                  columns={columns}
                  dataSource={this.state.dataSource2}
                  pagination={false}
            />
      </Card>
      

      提取出onRowClick方法:获取当前点击行的数据项record和索引index

      //点击某一行 record:当前点击行的数据项 index:当前点击行的索引
      onRowClick = (record, index) => {
              let selectKey = [index];
              Modal.info({
                  title: '信息',
                  content: `用户名:${record.userName},用户爱好:${record.interest}`
              });
              this.setState({
                  selectedRowKeys: selectKey,
                  selectedItem: record
              })
      }
      

        

    四、表格复选

     

    • 配置rowSelection属性对象
    1. 添加onChange事件
    2. selectedRowKeys:当前选中的行索引
    3. selectedRows:当前选中的行对象
      const rowCheckSelection = {
                  type: 'checkbox',
                  selectedRowKeys,
                  onChange: (selectedRowKeys, selectedRows) => {
                      // let ids = []
                      // selectedRows.map((item) => {
                      //    ids.push(item.id)
                      // })
                      this.setState({
                          selectedRowKeys, //必需
                          // selectedIds: ids,
                          selectedRows
                      })
                  }
      }
      
    • 选中多行执行操作

    1. 获取state中的seletedRows对象,遍历得到item对象

    2. 利用item.id执行操作
    3. 执行完操作,需要重新刷新页面:调用this.request()

      //多选执行删除动作
      handleDelete = () => {
              let rows = this.state.selectedRows;
              let ids = [];
              rows.map((item) => {
                  ids.push(item.id)
              })   
              Modal.confirm({
                  title: '删除提示',
                  content: `您确定要删除这些数据吗?${ids.join(',')}`,
                  onOk: () => {
                     message.success('删除成功')
                     this.request();  //重新刷新页面
                  }
              })
      }
    4. request方法中:当获取数据成功后,重置state中当前选中项参数均为空

      selectedRowKeys: [], //重置
      selectedRows: null,
    • 其它,同单选

      <Card title="Mock-复选" style={{margin: '10px 0'}}>
              <div style={{marginBottom: 10}}>
                     <Button onClick={this.handleDelete}>删除</Button>
              </div>
              <Table 
                      bordered
                      rowSelection={rowCheckSelection}
                      onRow={(record, index) => {
                              return {
                                  onClick: () => { 
                                      this.onRowClick(record, index)
                                  }  //点击行
                              }
                      }}
                      columns={columns}
                      dataSource={this.state.dataSource2}
                      pagination={false}
              />
      </Card>
      

        

    五、表格分页

    •  src->utils->utils.js封装pagination分页工具函数 【项目工程化】
      pagination(data,callback){
         return {
              onChange: (current) => {
                  callback(current)   //回调函数返回当前页
              },
              current: data.page,
              pageSize: data.page_size,
              total: data.total,
              showTotal: () => {
                  return  `共${data.total}条`
              },
              showQuickJumper: true  //是否快速跳转至某一页
         }
      }  

      注意:获取data对象的数据,需要符合Easy Mock中模拟数据的数据结构!!!

    • request方法中:当获取数据成功后,调用Utils.pagination()给state添加并配置pagination

      import Utils from './../../utils/utils'
      
      let _this = this; //保留外层this,否则this指向会有问题
      
      pagination: Utils.pagination(res,(current) => {
             _this.params.page = current;
             this.request();
      })
    • Table组件中使用pagination属性

      <Card title="Mock-表格分页" style={{margin: '10px 0'}}>
            <Table 
                      bordered
                      columns={columns}
                      dataSource={this.state.dataSource2}
                      pagination={this.state.pagination}
             />
      </Card>
      

       

    六、Loading拦截加载项

    •  index.html中:在<div id="root"></div>下配置全局html文件 【项目工程化】
      <div class="ajax-loading" id="ajaxLoading" style="display: none;">
            <div class="overlay"></div>
            <div class="loading">
                <img src="https://media.number-7.cn/ebike-h5/static/images/common/loading.gif" alt="">
                <span>加载中,请稍后...</span>
            </div>
      </div>
    • src->style->loading.less:同时 common.less中引入

      /** load **/
      .ajax-loading{
          display: none;
          .loading{
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%,-50%);
            padding:0 40px;
            height: 80px;
            line-height: 80px;
            background: rgba(0, 0, 0, 0.75);
            border-radius: 6px;
            text-align: center;
            z-index: 9999;
            font-size:@fontD;
            color:#fff;
            img{
               32px;
              vertical-align: middle;
            }
            span{
              margin-left:12px;
            }
          }
          .overlay{
            position: fixed;
            left: 0;
            right: 0;
            top: 0;
            bottom: 0;
            z-index: 9998;
            background: rgb(255, 255, 255);
            opacity: 0.1;
          }
        }
      
      @import './../style/loading.less';
    • src->axios->index.js:ajax方法中设置loading默认display block,当获取数据成功后,改为display none

      let loading;
      if(options.data && options.data.isShowLoading !== false){
               loading = document.getElementById('ajaxLoading');
               loading.style.display = 'block';
      }
      //其它代码
      .then((response)=>{
              if(options.data && options.data.isShowLoading !== false){
                          loading = document.getElementById('ajaxLoading');
                          loading.style.display = 'none';
              }
      

        

    七、实例代码

    • pages->table->basicTable.js:对应路由/admin/table/basic
    import React from 'react';
    import {Card, Table, Modal, Button, message} from 'antd';
    import axios from './../../axios/index'
    import Utils from './../../utils/utils'
    
    export default class BasicTables extends React.Component{
        state = {
            dataSource2: []
        }
        params = {
            page: 1
        }
        componentDidMount(){
            const dataSource = [   //数据源
                {
                    id: '0',
                    userName: 'Elena',
                    sex: '1',
                    state: '1',
                    interest: '1',
                    birthday: '2019-01-01',
                    address: '西虹市海淀区桃花公园',
                    time: '07:00'
                },
                {
                    id: '1',
                    userName: 'Mary',
                    sex: '1',
                    state: '2',
                    interest: '3',
                    birthday: '2019-01-01',
                    address: '西虹市海淀区桃花公园',
                    time: '07:00'
                },
                {
                    id: '2',
                    userName: 'Tom',
                    sex: '2',
                    state: '3',
                    interest: '4',
                    birthday: '2019-01-01',
                    address: '西虹市海淀区桃花公园',
                    time: '07:00'
                }
            ]
            dataSource.map((item, index) => {
                item.key = index;
            })
            this.setState({
                dataSource
            })
            this.request();
        }
    
        //动态获取mock数据
        request = () => {
            let _this = this;
            axios.ajax({
                url: '/table/list',
                data:{
                    params:{
                        page: this.params.page
                    },
                    // isShowLoading: false
                }
            }).then((res) => {
                if(res.code === 0){
                   res.list.map((item, index) => {
                       item.key = index
                   })
                   this.setState({
                       dataSource2: res.list,
                       selectedRowKeys: [], //重置
                       selectedRows: null,
                       pagination: Utils.pagination(res,(current) => {
                           _this.params.page = current;
                           this.request();
                       })
                   })
                }
            })
        }
    
        onRowClick = (record, index) => {
            let selectKey = [index];
            Modal.info({
                title: '信息',
                content: `用户名:${record.userName},用户爱好:${record.interest}`
            });
            this.setState({
                selectedRowKeys: selectKey,
                selectedItem: record
            })
        }
    
        // add = () => {
        //     let item = this.state.selectedItem;
        //     if(item.id){
    
        //     }
        // }
    
        //多选执行删除动作
        handleDelete = () => {
            let rows = this.state.selectedRows;
            let ids = [];
            rows.map((item) => {
                ids.push(item.id)
            })   
            Modal.confirm({
                title: '删除提示',
                content: `您确定要删除这些数据吗?${ids.join(',')}`,
                onOk: () => {
                   message.success('删除成功')
                   this.request();  //重新刷新页面
                }
            })
        }
    
        render(){
            const columns = [
                 {
                     title: 'id',   //表头标题
                     dataIndex: 'id' //数据源
                 },
                 {
                     title: '用户名',
                     dataIndex: 'userName'
                 },
                 {
                    title: '性别',
                    dataIndex: 'sex',
                    render(sex){
                        return sex === 1 ? '男' : '女'
                    }
                 },
                 {
                    title: '状态',
                    dataIndex: 'state',
                    render(state){
                        let config = {
                            '1': '咸鱼一条',
                            '2': '人民公仆',
                            '3': '医院护士',
                            '4': '科技公司FE',
                            '5': '创业者'
                        }
                        return config[state]
                    }
                 },
                 {
                    title: '爱好',
                    dataIndex: 'interest',
                    render(abc){
                        let config = {
                            '1': '游泳',
                            '2': '打篮球',
                            '3': '踢足球',
                            '4': '跑步',
                            '5': '爬山',
                            '6': '骑行',
                            '7': '桌球',
                            '8': '麦霸'
                        }
                        return config[abc]
                    }
                 },
                 {
                    title: '生日',
                    dataIndex: 'birthday'
                 },
                 {
                    title: '地址',
                    dataIndex: 'address'
                 },
                 {
                    title: '早起时间',
                    dataIndex: 'time'
                 }       
            ]
            const selectedRowKeys = this.state.selectedRowKeys;
            const rowSelection = {
                type: 'radio',
                selectedRowKeys
            }
            const rowCheckSelection = {
                type: 'checkbox',
                selectedRowKeys,
                onChange: (selectedRowKeys, selectedRows) => {
                    // let ids = []
                    // selectedRows.map((item) => {
                    //    ids.push(item.id)
                    // })
                    this.setState({
                        selectedRowKeys, //必需
                        // selectedIds: ids,
                        selectedRows
                    })
                }
            }
            return (
                <div>
                    <Card title="基础表格">
                        <Table 
                            bordered
                            columns={columns}
                            dataSource={this.state.dataSource}
                            pagination={false}
                        />
                    </Card>
                    <Card title="Mock-动态数据渲染表格" style={{margin: '10px 0'}}>
                        <Table 
                            bordered
                            columns={columns}
                            dataSource={this.state.dataSource2}
                            pagination={false}
                        />
                    </Card>
                    <Card title="Mock-单选" style={{margin: '10px 0'}}>
                        <Table 
                            bordered
                            rowSelection={rowSelection}
                            onRow={(record, index) => {
                                return {
                                    onClick: () => { 
                                        this.onRowClick(record, index)
                                    }  //点击行
                                }
                            }}
                            columns={columns}
                            dataSource={this.state.dataSource2}
                            pagination={false}
                        />
                    </Card>
                    <Card title="Mock-复选" style={{margin: '10px 0'}}>
                        <div style={{marginBottom: 10}}>
                            <Button onClick={this.handleDelete}>删除</Button>
                        </div>
                        <Table 
                            bordered
                            rowSelection={rowCheckSelection}
                            onRow={(record, index) => {
                                return {
                                    onClick: () => { 
                                        this.onRowClick(record, index)
                                    }  //点击行
                                }
                            }}
                            columns={columns}
                            dataSource={this.state.dataSource2}
                            pagination={false}
                        />
                    </Card>
                    <Card title="Mock-表格分页" style={{margin: '10px 0'}}>
                        <Table 
                            bordered
                            columns={columns}
                            dataSource={this.state.dataSource2}
                            pagination={this.state.pagination}
                        />
                    </Card>
                </div>
            )
        }
    }  

    注:项目来自慕课网

  • 相关阅读:
    查找第K小数
    比较奇偶数个数
    哈夫曼树练习
    数字转二进制数练习
    随笔
    字符串反码(练习)
    eclipse构建maven的web项目
    mysql中的一些操作语句,留存
    urllib2功能说明
    Python-第三方库requests详解
  • 原文地址:https://www.cnblogs.com/ljq66/p/10206605.html
Copyright © 2020-2023  润新知