【共享單車】—— 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{
            width: 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>
        )
    }
}  

注:項目來自慕課網


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM