看起來複雜了點,不過理解後就還好了。
基本用法
表格會用 <Table />
來表示,並且接收 dataSource
跟 columns
這兩個 props。
dataSource
跟 columns
的值都是 Array,來看 code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const dataSource = [ { key: '1', name: 'PeaNu', age: 23, address: '高雄市' } ]
const columns = [ { title: '姓名', dataIndex: 'name', key: 'name' } ]
|
附註:key
是用來給 React 渲染列表用的,預設是用 key
來表示,但你也可以用 rowKey
來重新定義,後面會再解釋。
首先 dataSource
裡面會放我們要呈現的資料,等一下會跟 columns
來做映射。
而 columns
中最重要的欄位是 dataIndex
,填入的東西就代表 dataSource
中的哪個 key?像上面填了 name
,所以就會到 dataSource
找到 name: 'PeaNu'
然後顯示到畫面上;至於 title
的話是表格的欄位名稱。
上面的輸出結果如下:
重新設定 key 的值
前面有說 key
這個值是用來給 React 渲染列表用的,不過如果資料是透過 API 取得的話,通常不會有 key
這個欄位,那怎麼辦?
這時候就要在 <Table />
加上 rowKey
這個屬性,告訴他「我要拿哪個欄位來當做 key
」。
舉例來說,假設 API 拿到的資料如下:
1 2 3 4 5 6 7 8 9 10 11 12
| const dataSource = [ { userId: '1', name: 'PeaNu', gender: 'M' }, { userId: '2', name: 'PPB', gender: 'F' } ]
|
那 <Table />
就會長這樣:
1
| <Table rowKey='userId' dataSource={dataSource} columns={columns} />
|
這樣就可以解決 key 的問題了。
巢狀的資料結構
如果現在資料變成這樣:
1 2 3 4 5 6 7 8 9 10
| const dataSource = [ { name: 'PeaNu', age: 23, address: '高雄市', family: { wife: 'PPB' } } ]
|
那 columns
就得這樣寫:
1 2 3 4 5 6
| const columns = [ { title: 'Wife', dataIndex: ['family', 'wife'] } ]
|
如果現在又變成這樣:
1 2 3 4 5 6 7 8 9 10 11 12
| const dataSource = [ { name: 'PeaNu', age: 23, address: '高雄市', family: [ { wife: 'PPB' } ] } ]
|
那 columns
就得這樣寫:
1 2 3 4 5 6
| const columns = [ { title: 'Wife', dataIndex: ['family', '0', 'wife'] } ]
|
重新設定輸出到畫面的值
有時候我們從 API 拿到的值不會想直接放到畫面上,例如:
1 2 3 4 5 6 7 8 9 10
| const dataSource = [ { name: 'PeaNu', gender: 'M' }, { name: 'PPB', gender: 'F' } ]
|
這時候就可以用 render
這個屬性來處理:
1 2 3 4 5 6 7 8 9 10 11 12 13
| const columns = [ { title: 'Name', dataIndex: 'name' }, { title: 'Gender', dataIndex: 'gender', render: (typeChar: string): string => { return typeChar === 'F' ? '女' : '男' } } ]
|
也可以用縮寫的方式來寫:
1 2 3 4 5 6 7 8 9 10 11 12 13
| const columns = [ { title: 'Name', dataIndex: 'name' }, { title: 'Gender', dataIndex: 'gender', render(value: string): string { return value === 'F' ? '女' : '男' } } ]
|
想再任性一點嗎?你甚至可以直接回傳一個 JSX:
1 2 3 4 5 6 7 8 9 10 11 12 13
| const columns = [ { title: 'Name', dataIndex: 'name' }, { title: 'Gender', dataIndex: 'gender', render(value: string): React.ReactElement { return typeChar === 'M' ? <h1>女</h1> : <h1>男</h1> } } ]
|
加上事件處理
除了 dataSource
跟 columns
以外,還有一個 onRow
屬性可以用,用起來會像這樣子:
1 2 3 4 5 6 7 8 9 10 11 12
| <Table dataSource={testData} columns={testColumns} onRow={(record: any) => { return { onClick: (event) => { console.log('record', record) console.log('click') } } }} />
|
onRow
會放一個 function,這個 function 會回傳一個物件,裡面就可以放 event 跟 handler。
至於 record
的值會是觸發事件的「那個欄位」的 dataSource
值。
我知道聽起來講超級無敵難懂,所以一步一步來解釋吧。
假設 dataSource
長這樣:
1 2 3 4 5 6 7 8 9 10
| const dataSource = [ { name: 'PeaNu', gender: 'M' }, { name: 'PPB', gender: 'F' } ]
|
然後我點了 PeaNu 那一排:
那 record
的值就會是:
1 2 3 4
| { name: 'PeaNu', gender: 'M' }
|
加上滾軸
如果沒有做額外設定的話,預設的 <Table />
會「自適應」做縮放,直到放不下時,會在視窗產生滾軸,像這樣:
有沒有辦法讓滾軸產生在「表格中」就好?還真的有,就是加上 scroll
屬性:
1 2 3 4 5 6 7 8 9
| <Table rowKey='id' dataSource={testData} columns={testColumns} scroll={{ x: 1000, y: 150 }} />
|
裡面要傳一個物件,然後指定 x 軸和 y 軸的「寬度」。這兩個的行為不太一樣,要分清楚。
y 軸的概念比較簡單,想成是總高度就好。例如我設為 150
,那表格的高度就會固定成 150px
,當資料超過 150px
的話就會產生滾軸。
至於 x 軸的部分,你可以這樣記「當視窗小於 x 時,我希望表格的寬度有多寬」。所以我設為 1000
時,就代表當視窗寬度低於 1000 時表格的寬度會固定在 1000px
,然後產生滾軸。
這樣會好記一點,所以這樣記就好。
加上排序和過濾
如果我有這樣的表格:
我希望可以加上升冪跟降冪排序的選項,那我可以在 columns 加上這樣的設定:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const columns = useRef([ { title: 'User id', dataIndex: 'id', sorter: (a: any, b: any) => a.id - b.id }, { title: 'First name', dataIndex: 'first_name' }, { title: 'Last name', dataIndex: 'last_name' }, { title: 'Email', dataIndex: 'email' } ])
|
也可以加上預設值,不過要注意一下 type 的問題,沒設定好的話會出錯:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| const columns = useRef<any[]>([ { title: 'User id', dataIndex: 'id', sorter: (a: any, b: any) => a.id - b.id, defaultSortOrder: 'ascend' }, { title: 'First name', dataIndex: 'first_name' }, { title: 'Last name', dataIndex: 'last_name' }, { title: 'Email', dataIndex: 'email' } ])
|
接著,如果我希望加上過濾的功能,像這樣:
那就要在 columns
上加上兩個東西:
filters
,一個 Array
onFilter
,一個 function
一樣來看 code 解釋:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| const columns = useRef<any[]>([ { title: 'User id', dataIndex: 'id' }, { title: 'First name', dataIndex: 'first_name', filters: [ { text: 'George', value: 'George' }, { text: 'Janet', value: 'Janet' }, { text: 'Emma', value: 'Emma' } ], onFilter: (value: any, record: any) => { console.log('value', value) console.log('record', record) console.log('filter', record.first_name === value) return record.first_name === value } }, { title: 'Last name', dataIndex: 'last_name' }, { title: 'Email', dataIndex: 'email' } ])
|
這樣就可以實現過濾的功能了。
結尾
最後綜合以上所學,我做了一個簡單的範例,有需要的話可以去參考看看。