1. 程式人生 > 程式設計 >ant design vue巢狀表格及表格內部編輯的用法說明

ant design vue巢狀表格及表格內部編輯的用法說明

實現效果:

ant design vue巢狀表格及表格內部編輯的用法說明

因為pro手腳架中封裝的s-table不支援expand和expandedRowsChange事件,無法實現根據展開節點獲取其內部資料的需求,因此直接使用a-table元件

表格外層可以翻頁,查詢攜帶頁碼引數

<a-table
size="default"
rowKey="dict_id" //根據自己資料內部關鍵針設定
ref="table"
@expandedRowsChange="expandedRowsChange"
@expand="expand" // 展開表格節點操作
@change="change" // 外層表格中排序,翻頁,修改頁面數量等操作
:expandedRowKeys="expandedRowKeys" // 操作展開的節點
:pagination="pagination" // 頁碼引數
:columns="columns" // 表頭
:dataSource="loadData" // 資料
>
<a-table
size="default"
style="margin-bottom:0;"
rowKey="key"
slot="expandedRowRender" // 以內層方式展現
:columns="innerColumns"
:dataSource="data"
:pagination="false"
:loading="innerloading"
@change="innerhandleChange"
>
<template v-for="(col,i) in ['item_text','item_value','item_checked','item_remark','item_sort','item_status']" :slot="col" slot-scope="text,record">
<a-input
:key="col"
v-if="record.editable"
style="margin: -5px 0"
:value="text"
:placeholder="innerColumns[i].title"
@change="e => handleChange(e.target.value,record.key,col)"
/>
<template v-else>{{ text }}</template>
</template> // 內部表格可編輯模板
<template slot="operation" slot-scope="text,record">
<template v-if="record.editable">
<span v-if="record.isNew">
<a @click="saveRow(record)">新增</a>
<a-divider type="vertical" />
<a-popconfirm title="是否要刪除此行?" @confirm="remove(record.key)">
<a>刪除</a>
</a-popconfirm>
</span>
<span v-else>
<a @click="saveRow(record)">儲存</a>
<!-- <a-divider type="vertical" />
<a @click="cancel(record.key)">取消</a> -->
</span>
</template> // 內部表格新增模板
<span v-else>
<a @click="toggle(record)">編輯</a>
</span>
</template>
</a-table>
<div
slot="expandedRowRender"
style="margin: 0">
<a-button style="width: 100%; margin-top: 16px; margin-bottom: 8px" type="dashed" icon="plus" @click="newMember">新增屬性</a-button>
</div>
<span slot="action" slot-scope="text,record">
<a @click="handleEdit(record)">編輯</a>
</span>
</a-table>

主要資料:

  expandedRowKeys: [],// 表頭
  columns: [
  {
   title: '字典編碼',dataIndex: 'dict_code'
  },{
   title: '字典名稱',dataIndex: 'dict_name'
  },{
   title: '狀態',dataIndex: 'dict_status'
  },{
   title: '字典描述',dataIndex: 'dict_remark'
  },{
   title: '操作',width: '150px',dataIndex: 'action',scopedSlots: { customRender: 'action' }
  }
  ],loadData: [],innerColumns: [
  {
   title: '欄位名',dataIndex: 'item_text',key: 'item_text',width: '15%',scopedSlots: { customRender: 'item_text' }
  },{
   title: '欄位值',dataIndex: 'item_value',key: 'item_value',scopedSlots: { customRender: 'item_value' }
  },{
   title: '預設選中(0:否,1:是)',dataIndex: 'item_checked',key: 'item_checked',width: '10%',scopedSlots: { customRender: 'item_checked' }
  },{
   title: '備註',dataIndex: 'item_remark',key: 'item_remark',width: '20%',scopedSlots: { customRender: 'item_remark' }
  },{
   title: '排序號',dataIndex: 'item_sort',key: 'item_sort',sorter: true,scopedSlots: { customRender: 'item_sort' }
  },{
   title: '狀態(1:正常,2:異常)',dataIndex: 'item_status',key: 'item_status',scopedSlots: { customRender: 'item_status' }
  },key: 'action',scopedSlots: { customRender: 'operation' }
  }
  ],data: [],innerloading: false,parameter: {
  pageNo: 1,pageSize: 10
  },// 排序引數
  sortedInfo: null,pagination: {
  total: 1,current: 1,showTotal: total => `共 ${total} 條記錄 第 ${this.pagination.current} / ${Math.ceil(total / this.pagination.pageSize)} 頁`,showQuickJumper: true,showSizeChanger: true,pageSize: 10
  }

初始進入頁面時,需要獲取外層表格

使用初始引數parameter請求第一頁資料,從返回資料中對pagination重置翻頁元件內部引數,主要有當前頁,頁碼總量,頁碼大小

getDictList(this.parameter)
  .then(res => {
   if (res.code === '200') {
   console.log(res)
   this.loadData = res.data
   this.pagination.total = res.totalCount
   this.pagination.current = res.pageNo
   this.pagination.pageSize = res.pageSize
   } else {
   this.$message.error(res.message)
   }
  })

展開外層資料節點獲取內部資料:

expand (expanded,record) {
  this.expandedRowKeys = [] // 重置展開節點,只展開當前點選的節點(內部資料呼叫模板,無法做到同時幾個內層表格資料直接快取在頁面)
  if (expanded) {
  this.expandedRowKeys = [record.dict_id]
  this.getDictItem() // 獲取表格內部資料
  }
  console.log(expanded,record)
 },// 展開節點後獲取內部表格資料
getDictItem (obj) {
  let searchparam = { dict_id: this.expandedRowKeys[0] }
  if (obj) { // 內部表格除了根據其父節點id查詢的條件外,還支援排序,因此需要整合排序引數
  searchparam = Object.assign(searchparam,obj)
  }
  this.innerloading = true
  getDictItemList(searchparam).then(res => {
  if (res.code === '200') {
   this.data = res.data
   this.innerloading = false
  } else {
   this.$message.error(res.message)
  }
  })
 },// 外層表格操作
 change (pagination,filters,sorter) { // 對頁面大小,篩選,排序等條件修改後重新查詢資料
  this.pagination = pagination
  this.parameter.pageNo = pagination.current
  this.parameter.pageSize = pagination.pageSize
  this.getDict()
  console.log('pagination',pagination)
  console.log('filters',filters)
  console.log('sorter',sorter)
 },/* 內層表格操作 */
 innerhandleChange (pagination,sorter) {
  console.log('Various parameters',pagination,sorter)
  this.sortedInfo = {
  sortField: sorter.field,sortOrder: sorter.order
  }
  this.getDictItem(this.sortedInfo)
 },

至此,展示功能已經幾乎做完啦,現在是內部表格的編輯與新增功能

handleChange (value,key,column) { // 實時更新表格中各個輸入框的狀態
  const newData = [...this.data]
  const target = newData.filter(item => key === item.key)[0]
  if (target) {
  target[column] = value
  this.data = newData
  }
 },toggle (data) { // 切換輸入框與文字狀態,實現展示與編輯功能
  const target = this.data.filter(item => item.key === data.key)[0]
  target.editable = !target.editable
  console.log(this.data)
 },newMember () { // 新增內容後的資料欄位
  this.data.push({
  'item_text': '','item_value': '','item_checked': '','item_remark': '','item_sort': '','item_status': '',key: this.data.length,editable: true,isNew: true
  })
 },saveRow (record) {
  this.innerloading = true
  if (!record.item_text || !record.item_value) { // 對必填項進行管控
  this.innerloading = false
  this.$message.error('請至少填寫填寫欄位名和欄位值。')
  return
  }
  record.item_checked = record.item_checked || 0 // 設定預設值
  record.item_sort = record.item_sort || 1
  record.item_status = record.item_status || 1
  record.dict_id = this.expandedRowKeys[0]
  if (record.item_id) { // 修改
  updateItem(record).then(res => {
   if (res.code === '200') {
   this.$message.success(res.message)
   this.getDictItem() // 修改成功後重新獲取當前內部表格資料
   } else {
   this.$message.error(res.message)
   }
  })
  } else {
  addItem(record).then(res => {
   if (res.code === '200') {
   this.$message.success(res.message)
   this.getDictItem()
   } else {
   this.$message.error(res.message)
   }
  })
  }
 },cancel (key) {
  const target = this.data.filter(item => item.key === key)[0]
  target.editable = false
 },remove (key) {
  const newData = this.data.filter(item => item.key !== key)
  this.data = newData
 },/* 內層表格操作結束 */

外層表格與記憶體表格資料示例:

{
 "success": true,"code": "200","message": "分頁查詢成功","data": [{
 "dict_id": 1,"dict_code": "common_org_type","dict_name": "機構類別","dict_pid": null,"dict_status": 1,"dict_remark": "機構類別"
 },{
 "dict_id": 2,"dict_code": "common_user_type","dict_name": "人員類別","dict_remark": "人員類別"
 },{
 "dict_id": 48,"dict_code": "cdsfcsdcf","dict_name": "修改屬性1","dict_remark": ""
 },{
 "dict_id": 49,"dict_code": "bugbugbug","dict_name": "有字典id",{
 "dict_id": 50,"dict_code": "1","dict_name": "名稱","dict_remark": "1"
 },{
 "dict_id": 51,"dict_name": "1","dict_remark": null
 },{
 "dict_id": 52,{
 "dict_id": 53,{
 "dict_id": 54,{
 "dict_id": 55,"dict_code": "dbhasuiuh","dict_name": "測試字典1","dict_remark": "備註"
 }],"totalCount": 11,"pageNo": 1,"pageSize": 10,"totalTag": 1
}
{
 "success": true,"message": "查詢成功","data": [{
 "item_id": 2,"dict_id": 1,"item_text": "外部","item_value": "2","item_status": 1,"item_sort": 2,"item_remark": null,"item_checked": 1,"editable": 0 // 寫死就行了 一定要有 用於內部表格編輯功能
 },{
 "item_id": 1,"item_text": "內部","item_value": "1","item_sort": 1,"item_remark": "1","editable": 0
 }]
}

補充知識:ant design Table可編輯的單元格改進版

antd官方也有給文件,但是超級麻煩,程式碼量還超級多,改編了一下

如圖:

ant design vue巢狀表格及表格內部編輯的用法說明

這裡table的columns的寫法,如下:

const columns2 = [
{
title: '尺寸名稱',dataIndex: 'name',filterDropdown: true,filterIcon: <Icon type="edit"/>,render: () => <Input />,},{
title: '標準尺寸',dataIndex: 'standard',render:() => <Input />,{
title: '上偏差',dataIndex: 'upper_deviation',{
title: '下偏差',dataIndex: 'lower_deviation',{
title: '工序',dataIndex: 'procedure',render: () => 
<Select>
  <Option value='1'>1</Option>  
  <Option value='2'>2</Option> 
</Select>
},{
title: '操作',dataIndex: 'operation',render: (text,record) => (
this.state.size.length >= 1
? (
<Popconfirm title="確定刪除該資訊?" onConfirm={() => this.handleDelete(record.key)}>
<a href="javascript:;">刪除</a>
</Popconfirm>
) : null
),}
];

其中

filterDropdown: true,

filterIcon: <Icon type="edit"/>,

這兩個是用於給表頭新增圖示,不需要可以不寫

實現可編輯表格最重要的是吧這個表格所有欄位都變成可控欄位,這樣就可以實現對錶格資料的提交的基本操作

就拿我這裡面的尺寸名稱來說,這個欄位叫name ,這裡的render就要修改成render: (text,record) => <Input value={text} onChange={(e) => this.handleChange({name: e.target.value},record)}/>,

這裡引數text可以理解為 input的初始值,onChange事件是吧這個input變成可控的元件,handleChange這裡有兩個引數,這裡“”name: e.target.value“”必須要這麼傳,目的是把改元件的值跟name進行繫結。

handleChange 方法

handleChange = (value,record) => {
for (var i in value) {
record[i] = value[i];//這一句是必須的,不然狀態無法更改
this.setState({
size: this.state.size.map((item,key) => item.key == record.key ? {...item,[i]: value[i]} : item)
})
}
}

這裡我把這個可編輯表格的值存在state中的size中,通過key進行匹配(這裡key代表我這個表格的rowkey,也就是用來區分行資料的一個標識),然後修改指定行的指定資料,通過改變state中的size更新檢視,同時吧更改的資料替換掉原來的 這就實現了對錶格資料的實時監聽,同時表格的所有資料存在了state中的size中,想要獲取表格資料直接用this.state.size即可。

(這裡需要注意的時,如果把表格中的某個欄位,比如說name設定成表格的rowkey,就會發生name欄位只能輸入單個字元就會失去焦點的情況)

以上這篇ant design vue巢狀表格及表格內部編輯的用法說明就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。