亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

React Ant Design樹形表格的復雜增刪改操作

 更新時間:2020年11月02日 17:04:41   作者:窮途陌路  
這篇文章主要介紹了React Ant Design樹形表格的復雜增刪改操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

最近因為業(yè)務接觸了antd,使用antd完成一個復雜的樹形表格的顯示以及修改。在這其中遇見了不少坑,很多功能antd只寫了初步的功能,更為細化的功能只能自己完善。踩過的坑都寫在了這里。

樹形表格的顯示

在antd中對于表格的key值有著嚴格的控制,每一個row都必須有一個獨一無二的key值,可以是數(shù)字也可以是字符串。這一點和我曾經(jīng)使用過得iview有著很大的區(qū)別。react使用key來代表每一行是為了避免重新渲染的問題,這個優(yōu)化也在實際的開發(fā)中帶來了不少的問題。比如新建行時需要自定義新key。

下面直接上一下代碼及代碼效果,這是一個三級的樹形表格,且其中包含二級標題。

最終效果 ​

colums標題: 簡易版標題,隨著功能的增加,我們將增加colums的復雜度。

let columns = [
 {
  title: '題目',
  dataIndex: 'text'
 },
 {
  title: '類型',
  children: [
   {
    title: '一級',
    dataIndex: 'text1'
   },
   {
    title: '二級',
    dataIndex: 'text2',
   }]
 },
 {
  title: '內(nèi)容',
  dataIndex: 'content'
 },
 {
  title: '答案',
  dataIndex: 'answer',
 },
 {
  title: '類型',
  dataIndex: 'mark_type',
  className: 'line'
 },
 {
  title: '版本',
  dataIndex: 'version',
  className: 'line'
 },
 {
  title: '一級內(nèi)容點',
  dataIndex: 'value1',
  className: 'line'
 },
 {
  title: '二級內(nèi)容點',
  dataIndex: 'value2',
  className: 'line'
 },
 {
  title: '操作',
  key: 'action',
  width: 205
 }
];

data數(shù)據(jù):

let data = [{
   "key": 1,
   "text": "題目一",
   "children": [{
    "key": 11,
    "text1": "數(shù)學一",
    "children":[]
   }, {
    "key": 12,
    "text1": "語文一",
    "value1": "語文",
    "children": [{
     "key": 121,
     "value2": "選擇",
     "text2": "選擇題",
     "content": "題目內(nèi)容",
     "answer": "A",
     "mark_type": "1",
     "version": "1"
    },{
     "key": 122,
     "value2":"填空",
     "text2": "填空題",
     "content": "題目內(nèi)容",
     "answer": "梅花",
     "mark_type": "1",
     "version": "1"
    },{
     "key": 123,
     "value2": "閱讀",
     "text2": "閱讀題",
     "content": "題目內(nèi)容",
     "answer": "野蠻生長",
     "mark_type": "1",
     "version": "1"
    },{
     "key": 124,
     "value2": "文言文",
     "text2": "文言文",
     "content": "題目內(nèi)容",
     "answer": "滕王閣序",
     "mark_type": "1",
     "version": "1"
    }],
   }],
  }, {
   "key": 2,
   "text": "題目二",
   "children": [ {
    "key": 21,
    "text1": "英語一",
    "value1": "英語",
    "children": [{
     "key": 211,
     "value2": "完型",
     "text2": "完形填空",
     "content": "題目內(nèi)容",
     "answer": "ABC",
     "mark_type": "2",
     "version": "1"
    },{
     "key": 212,
     "value2": "一級代碼",
     "text2": "選擇",
     "content": "題目內(nèi)容",
     "answer": "D",
     "mark_type": "2",
     "version": "1"
    }],
   }],
  }];

增加子項數(shù)據(jù)

增加子項數(shù)據(jù)使用操作中的增加按鈕進行增加,增加按鈕設置為圖形,更為形象具體清晰化。

 //button樣式使用antd自帶icon樣式
<Button type="primary" shape="circle" icon="plus" size={'small'}
   onClick={this.handleAdd.bind(this, record)}
 />

注意事項:

1、對于最子項來說沒有增加子項選擇,需要對不同數(shù)據(jù)行進行不同處理

2、不同數(shù)據(jù)行新增數(shù)據(jù)的內(nèi)容不同,字段也不同

3、新增之后需要點擊確認或者取消

4、加入數(shù)據(jù)點擊確認之后需要添加于當前key下的children中

本想使用antd自帶的editable屬性,但是這個屬性不支持二級標題的編輯,所以只有自己寫render

這個問題,在7102年就提出來了,但是已經(jīng)8102年了快9102年都沒有更新。

新增一級類型題目樣式

新增二級類型題目樣式

這里就部分render代碼:

//分級標題
{
 title: '類型', 
 children: 
 [{
  title: '一級',
  dataIndex: 'text1',
  render: (text, record) => {
   if (this.state.isEditing && this.state.editingOneKey === record.key)
    return <Input defaultValue={text} onChange={(e) => { this.changeEdit(e, record.key, 'text1') }} />
   return text
  }
 },
 {
  title: '二級',
  dataIndex: 'text2',
  render: (text, record) => {
   if (this.state.isEditing && this.state.editingTwoKey === record.key)
    return <Input defaultValue={text} onChange={(e) => { this.changeEdit(e, record.key, 'text2') }} />
   return text
  }
 }]
}

//select選擇
{
 title: '內(nèi)容',
 dataIndex:'content',
 render:(text, record) => {
  if (text === 0)
   text = '內(nèi)容一';
  if (text === 1)
   text = '內(nèi)容二';
  if (this.state.isEditing && this.state.editingTwoKey === record.key) {
   return <Select defaultValue={text} onChange={(e) => {
    this.changeEdit(e, record.key, 'flag')
   }} getPopupContainer={triggerNode => triggerNode.parentNode}>
    <Option value='0'>有效</Option>
    <Option value='1'>無效</Option>
   </Select>
  }
  return text
 }
}

注意展開

如果對一行未展開的行下新增數(shù)據(jù),那么無法看到打開的編輯狀態(tài)是一個非常糟糕的問題。所以我們需要在新增子項的時候自動展開父項。

//steate初始化 
expandedRows: [] //展開行
//render 初始化
<Table
  bordered
  expandedRowKeys={this.state.expandedRows}
  onExpandedRowsChange={this.changeExpandedRows.bind(this)}
/>

//自動展開變化,獲取當前展開行
changeExpandedRows = (expandedRows) => {
  this.setState({
   expandedRows
  })
 };

//增加函數(shù)中
let rows = this.state.expandedRows;
rows.push(record.key);
this.setState({
 expandedRows: rows
});

刪除行數(shù)據(jù)

刪除在antd中相較比較簡單,因為antd的table每行都有key屬性,key是唯一且必須的屬性,所以只要過濾掉包含目的key的數(shù)據(jù)即可視為刪除。因為這是樹形數(shù)據(jù),普通的遍歷無法進行操作,所以使用深度優(yōu)先遍歷來進行數(shù)據(jù)處理,也可以使用廣度優(yōu)先,根據(jù)數(shù)據(jù)來變更。

handleDelete = (key) => {
  let data = this.state.data;
  data = dsFilter(data, key);

  this.setState({
   data
  });

  function dsFilter(dealData, dealKey) {
   for (let i = 0; i < dealData.length; i++) {
    if (dealData[i].children && dealData[i].children.length > 0) {
     dealData[i].children = dsFilter(dealData[i].children, dealKey);
    }
   }
   return dealData.filter(item => item.key !== dealKey);
  }
 };

修改某些字段

修改和新增的colums相同,不過修改需要保存之前的值。需要在input或select中設置defaultValue={text}來保證初始值相同

保存

無論是新增修改還是刪除,都需要進行保存。這里使用✓和✗ 來代表確定和取消。

同時需要注意,如果在一行的編輯中點擊其他行的操作,需要將之前行的操作視為取消。

<div>
 <Button shape="circle" icon="check" size={'small'} style={{ backgroundColor: '#65BF34', color: '#FFF', border: 'none' }}
   onClick={this.saveEdit.bind(this, record.key)}
 />
 <Button shape="circle" icon="close" size={'small'} style={{ backgroundColor: '#FF3333', color: '#FFF', border: 'none' }}
   onClick={this.cancelEdit.bind(this, record.key)}
 />
</div>

修改順序

修改順序就是修改數(shù)據(jù)在數(shù)組中的順序,使用簡單的temp進行交換即可。

shiftUp = (key) => {
  let data = this.state.data;
  data = dsShift(data, key);
  this.setState({
   data
  });

  function dsShift(dealData, dealKey) {
   for (let i = 0; i < dealData.length; i++) {
    if (dealData[i].children && dealData[i].children.length > 0) {
     dealData[i].children = dsShift(dealData[i].children, dealKey);
    }
    if (dealData[i].key === dealKey) {
     if (i === 0) {
      message.warning('該行已置頂!');
      break;
     }
     let temp = dealData[i - 1];
     dealData[i - 1] = dealData[i];
     dealData[i] = temp;
     break;
    }
   }
   return dealData;
  }
 };

 shiftDown = (key) => {
  let data = this.state.data;
  data = dsShift(data, key);
  this.setState({
   data
  });

  function dsShift(dealData, dealKey) {
   for (let i = 0; i < dealData.length; i++) {
    if (dealData[i].children && dealData[i].children.length > 0) {
     dealData[i].children = dsShift(dealData[i].children, dealKey);
    }
    if (dealData[i].key === dealKey) {
     if (i === dealData.length - 1) {
      message.warning('該行已置尾!');
      break;
     }
     let temp = dealData[i + 1];
     dealData[i + 1] = dealData[i];
     dealData[i] = temp;
     break;
    }
   }
   return dealData;
  }
 };

總結

在進行表格數(shù)據(jù)操作中,需要進行變量的保存,這里就沒有多寫了??偟膩碚fantd是個好組件,大部分功能都很齊全,但是很多細節(jié)還是需要自己進行完善。

補充知識:Antd(Ant-design),嵌套子表格(expandedRowRender)的異步獲取數(shù)據(jù)

使用阿里的ant-design開源框架,要在表格里面嵌套子表格,需要在用戶點擊父表格的一行數(shù)據(jù)后,獲取該行的key,然后去異步請求后臺的數(shù)據(jù)用來填充子表格的內(nèi)容。

如果這樣寫(省略無關代碼):

expandedRowRender = (record) => {
 
  dispatch({
    type: 'flow/getPlanList',
    payload: {
      contractId: record.contract_id, // 該參數(shù)是從父表格帶過來的key
    },
    callback: () => {
      const {
       flow: { data },
      } = this.props; 
 
      this.setState({
       secData: data.list,
      });
 
      console.log("返回數(shù)據(jù)(PlanList):" + JSON.stringify(this.state.secData));
    }
  });
  
  return (
    <Table
      columns={secColumns}
      dataSource={this.state.secData}
      pagination={false}
    />
  );
};
 
render() {
  return(
    <Card>
     {this.renderForm()}
     <div>
       <Table
        expandedRowRender={this.expandedRowRender}
        loading={loading}
        rowSelection={rowSelection}
        dataSource={list}
        columns={columns}
        pagination={paginationProps}
        scroll={{ x: 2500}}
        size = 'middle' 
        expandRowByClick={true}
        onSelect={this.seFn}
       />
     </div>
    </Card>
  ) 
}

則會出現(xiàn)不斷的發(fā)起請求的現(xiàn)象:

這是因為,expandedRowRender 實際上是在 Table 組件的 render 方法中調(diào)用的,React render 中用 dispatch 會造成重復調(diào)用的問題,dispatch -> setState -> render -> dispatch -> setState -> render,循環(huán)往復。所以應該把 dispatch 放在 onExpand 中。

onExpand = (expanded, record) => {
  const { dispatch } = this.props;
 
  dispatch({
    type: 'flow/getPlanList',
    payload: {
     contractId: record.contract_id,
    },
    callback: () => {
      const {
        flow: { data },
      } = this.props; 
 
      this.setState({
        secData: data.list ,
      });
 
     console.log("返回數(shù)據(jù)(PlanList):" + JSON.stringify(this.state.secData));
    }
  });
}

但是單純的這樣做,又會帶來新的問題,就是子表格的所有數(shù)據(jù)都變成了相同的。

本人的解決辦法是使用鍵值對。

onExpand = (expanded, record) => {
  const { dispatch } = this.props;
 
  if (expanded === false) {
   // 因為如果不斷的添加鍵值對,會造成數(shù)據(jù)過于龐大,浪費資源,
   // 因此在每次合并的時候講相應鍵值下的數(shù)據(jù)清空
   console.log("合并!");
   this.setState({
    subTabData: {
     ...this.state.subTabData,
     [record.contract_id]: [] ,
    }
   });
  } else {
   console.log("展開!");
   dispatch({
    type: 'flow/getPlanList',
    payload: {
     contractId: record.contract_id,
    },
    callback: () => {
     const {
      flow: { data },
     } = this.props; 
 
     this.setState({
      subTabData: {
       ...this.state.subTabData,
       [record.contract_id]: data.list ,
      }
     });
 
     console.log("返回數(shù)據(jù)(PlanList):" + JSON.stringify(this.state.subTabData));
    }
   });
  }
 }

以上這篇React Ant Design樹形表格的復雜增刪改操作就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • 詳解React中錯誤邊界的原理實現(xiàn)與應用

    詳解React中錯誤邊界的原理實現(xiàn)與應用

    在React中,錯誤邊界是一種特殊的組件,用于捕獲其子組件樹中發(fā)生的JavaScript錯誤,并防止這些錯誤冒泡至更高層,導致整個應用崩潰,下面我們就來看看它的具體應用吧
    2024-03-03
  • vscode調(diào)試react?最初的源碼解析

    vscode調(diào)試react?最初的源碼解析

    這篇文章主要介紹了vscode調(diào)試react?最初的源碼,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友跟隨小編一起看看吧
    2023-11-11
  • React-Native TextInput組件詳解及實例代碼

    React-Native TextInput組件詳解及實例代碼

    這篇文章主要介紹了React-Native TextInput組件詳解及實例代碼的相關資料,需要的朋友可以參考下
    2016-10-10
  • 淺談react前后端同構渲染

    淺談react前后端同構渲染

    本篇文章主要介紹了淺談react前后端同構渲染,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • 如何在react項目中做公共配置文件

    如何在react項目中做公共配置文件

    這篇文章主要介紹了如何在react項目中做公共配置文件問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • React forwardRef的使用方法及注意點

    React forwardRef的使用方法及注意點

    React.forwardRef的API中ref必須指向dom元素而不是React組件,通過一段示例代碼給大家介紹了React forwardRef使用方法及注意點還有一些特殊情況分析,感興趣的朋友跟隨小編一起看看吧
    2021-06-06
  • useState?解決文本框無法輸入的問題詳解

    useState?解決文本框無法輸入的問題詳解

    這篇文章主要為大家介紹了useState?解決文本框無法輸入的問題詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • react在安卓中輸入框被手機鍵盤遮擋問題的解決方法

    react在安卓中輸入框被手機鍵盤遮擋問題的解決方法

    這篇文章主要給大家介紹了關于react在安卓中輸入框被手機鍵盤遮擋問題的解決方法,文中通過圖文以及示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起看看吧
    2018-09-09
  • React錯誤邊界Error Boundaries

    React錯誤邊界Error Boundaries

    錯誤邊界是一種React組件,這種組件可以捕獲發(fā)生在其子組件樹任何位置的JavaScript錯誤,并打印這些錯誤,同時展示降級UI,而并不會渲染那些發(fā)生崩潰的子組件樹
    2023-01-01
  • react實現(xiàn)拖拽模態(tài)框

    react實現(xiàn)拖拽模態(tài)框

    這篇文章主要為大家詳細介紹了react實現(xiàn)拖拽模態(tài)框,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08

最新評論