大家在做后臺管理系統的時候,寫的最多的可能就是表格頁面了,一般分三部分:搜索功能區、表格內容區和分頁器區。一般這些功能都是使用第三方組件庫實現,比如說element-ui,或者vuetify。這兩個組件庫都各有各的優點,但就table組件來說,我還是比較喜歡vuetify的實現,不用手寫一個個column,只要傳入headers的配置數組就行,甚至分頁器都內置在了table組件里,用起來十分方便。有興趣可以看看:vuetify data table。
上面是一個經典的用element-ui開發的table頁面,而且實際工作中如果每個table頁面都寫一遍,重復代碼太多了,所以不妨寫一個table模板組件,減少重復代碼。我的思路是這樣的:
搜索功能區:
提供searchBar插槽,可以自定義搜索輸入框,搜索、重置按鈕必有,新增按鈕通過props控制顯隱。這里對應的代碼如下:
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
|
genSearchBar() { if ( this .noSearchBar || ! this .$scopedSlots.searchBar) return '' ; return ( <el-form class= "seatch-form" inline={ true } label-width= "100" > { this .$scopedSlots.searchBar()} <el-button class= "filter-item" icon= "el-icon-search" type= "primary" onClick={ this .handleSearchBtnClick} > 查詢 </el-button> <el-button class= "filter-item" icon= "el-icon-refresh" onClick={ this .handleResetBtnClick} > 重置 </el-button> <el-button class= "filter-item" icon= "el-icon-plus" type= "primary" v-show={ this .showAddBtn} onClick={ this .handleAddBtnClick} > 新增 </el-button> </el-form> ); } |
表格內容區:
通過傳入headers自動生成columns,參數如下:
1
2
3
4
5
6
|
{ label: '性別' , prop: 'sex' , width: '180' , filter: 'sexFilter' } |
可對應如下代碼:
1
2
3
4
5
6
|
<el-table-column prop= "sex" label= "性別" width= "180" > <template slot-scope= "scope" >{{scope.row.sex | sexFilter}}</template> </el-table-column> |
注意,只支持全局filter。
如果你想自定義column,也提供tableColumn插槽,支持自定義column,可以如下配置:
1
2
3
|
{ prop: 'action' } |
1
2
3
4
5
6
7
8
9
|
<el-table-column prop= "action" label= "操作" width= "180" > <template slot-scope= "scope" > <el-button>編輯</el-button> <el-button>刪除</el-button> </template> </el-table-column> |
這樣,就會按傳入的prop匹配對應的column,十分方便。
實現代碼如下:
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
|
genTableSlot(h) { let customeColumns = this .$scopedSlots.tableColumn ? this .$scopedSlots.tableColumn() : []; return this .headers.map((item) => { // 根據item.prop判斷是否使用傳入的插槽內容 let foundItem = customeColumns.find( (ele) => ele.componentOptions && ele.componentOptions.propsData.prop === item.prop ); return foundItem ? foundItem : h( 'el-table-column' , { props: { ...item, }, scopedSlots: { default : (props) => { // 根據傳入的全局filter處理column數據 let filter = this .$options.filters[ item.filter ]; let itemValue = props.row[item.prop]; return h( 'span' , filter ? filter(itemValue) : itemValue ); }, }, }); }); } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
genTable(h) { return h( 'el-table' , { ref: 'tableRef' , props: { ... this .$attrs, data: this .data, }, on: { 'selection-change' : (val) => { this .$emit( 'selection-change' , val); }, }, }, [... this .genTableSlot(h)] ); } |
分頁器區:
如無特殊需求,分頁器功能一致,所以直接內置。
實現代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
genPagination() { return ( <div class= "pagination-wrap" > <el-pagination layout= "total,prev,pager,next,jumper" current-page={ this .current} page-size={ this .pageSize} total={ this .total} {...{ on: { 'current-change' : this .handleCurrentChange }, }} ></el-pagination> </div> ); } |
最后附完整代碼和demo:
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
<script> export default { name: 'TableTemplate' , props: { data: { type: Array, default : () => [], required: true , }, headers: { type: Array, default : () => [], required: true , }, current: { type: Number, default : 1, }, pageSize: { type: Number, default : 10, }, total: { type: Number, default : 0, }, noSearchBar: Boolean, showAddBtn: Boolean, }, mounted() { this .$nextTick(() => { this .$emit( 'search' ); }); }, methods: { genSearchBar() { if ( this .noSearchBar || ! this .$scopedSlots.searchBar) return '' ; return ( <el-form class= "seatch-form" inline={ true } label-width= "100" > { this .$scopedSlots.searchBar()} <el-button class= "filter-item" icon= "el-icon-search" type= "primary" onClick={ this .handleSearchBtnClick} > 查詢 </el-button> <el-button class= "filter-item" icon= "el-icon-refresh" onClick={ this .handleResetBtnClick} > 重置 </el-button> <el-button class= "filter-item" icon= "el-icon-plus" type= "primary" v-show={ this .showAddBtn} onClick={ this .handleAddBtnClick} > 新增 </el-button> </el-form> ); }, genTableSlot(h) { let customeColumns = this .$scopedSlots.tableColumn ? this .$scopedSlots.tableColumn() : []; return this .headers.map((item) => { // 根據item.prop判斷是否使用傳入的插槽內容 let foundItem = customeColumns.find( (ele) => ele.componentOptions && ele.componentOptions.propsData.prop === item.prop ); return foundItem ? foundItem : h( 'el-table-column' , { props: { ...item, }, scopedSlots: { default : (props) => { let filter = this .$options.filters[ item.filter ]; let itemValue = props.row[item.prop]; return h( 'span' , filter ? filter(itemValue) : itemValue ); }, }, }); }); }, genTable(h) { return h( 'el-table' , { ref: 'tableRef' , props: { ... this .$attrs, data: this .data, }, on: { 'selection-change' : (val) => { this .$emit( 'selection-change' , val); }, }, }, [... this .genTableSlot(h)] ); }, genPagination() { return ( <div class= "pagination-wrap" > <el-pagination layout= "total,prev,pager,next,jumper" current-page={ this .current} page-size={ this .pageSize} total={ this .total} {...{ on: { 'current-change' : this .handleCurrentChange }, }} ></el-pagination> </div> ); }, resetPagination() { this .$emit( 'update:current' , 1); }, handleCurrentChange(val) { this .$emit( 'update:current' , val); this .$emit( 'search' ); }, handleSearchBtnClick() { this .$emit( 'search' ); }, handleResetBtnClick() { this .resetPagination(); this .$emit( 'reset' ); }, handleAddBtnClick() { this .$emit( 'add' ); }, getTableRef() { return this .$refs.tableRef; }, }, render(h) { return ( <div> { this .genSearchBar()} { this .genTable(h)} { this .genPagination()} </div> ); }, }; </script> <style scoped> .seatch-form { text-align: left; } .pagination-wrap { margin-top: 20px; text-align: right; } </style> |
Demo:
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
<template> <div> <table-template border :headers= "headers" :data= "tableData" :current.sync= "current" :total= "total" ref= "tableTemplate" showAddBtn @search= "handleSearch" @reset= "handleReset" @add= "handleAdd" @selection-change= "handleSelectionChange" > <template #searchBar> <el-form-item label= "姓名:" prop= "title" > <el-input class= "filter-item" v-model= "searchForm.title" ></el-input> </el-form-item> </template> <template #tableColumn> <el-table-column prop= "selection" type= "selection" width= "55" ></el-table-column> <el-table-column prop= "test" label= "姓名" width= "180" > <template slot-scope= "scope" > <el-popover trigger= "hover" placement= "top" > <p>姓名:{{ scope.row.name }}</p> <p>住址:{{ scope.row.address }}</p> <div slot= "reference" class= "name-wrapper" > <el-tag size= "medium" >{{scope.row.name}}</el-tag> </div> </el-popover> </template> </el-table-column> </template> </table-template> </div> </template> <script> import TableTemplate from './TableTemplate' ; export default { name: 'Demo' , components: { TableTemplate, }, data() { return { current: 1, total: 100, headers: [ { prop: 'selection' , }, { label: '姓名' , prop: 'name' , width: '100' , }, { label: '年齡' , prop: 'year' , }, { label: '性別' , prop: 'sex' , width: 'sexFilter' , }, { prop: 'test' , }, ], tableData: [ { name: 'curry' , year: 18, sex: 'female' , address: '天安門' , }, ], searchForm: { title: '' , }, }; }, methods: { handleSearch() { console.log( this .current); }, handleReset() { this .searchForm = { title: '' , }; }, handleAdd() { console.log( '添加' ); }, handleSelectionChange(val) { console.log(val); }, getTableRef() { console.log( this .$refs.tableTemplate.getTableRef()); }, }, }; </script> |
以上就是element-ui封裝一個Table模板組件的示例的詳細內容,更多關于element-ui封裝組件的資料請關注服務器之家其它相關文章!
原文鏈接:https://segmentfault.com/a/1190000038785865