一、el-table多选分页时,记住其他页的选中状态
实现方法:
核心是el-table-column的reserve-selection属性
image.png
1.通过type=“selection”设置复选框列,重点在于 reserve-selection 属性,设置为true时,数据更新之后保留之前选中的数据。
2.需要表格属性“row-key”的配合,在使用 reserve-selection 功能的情况下,该属性是必填的。将row-key设置为表格中唯一的字段名称(例如programId)。这样就实现了后端分页在翻页或切换条数时,记住之前的复选框选项。
1<el-table
2 :data="tableData"
3 :row-key="getRowKey"
4 @selection-change="handleSelectionChange"
5 >
6 <el-table-column
7 type="selection"
8 width="55"
9 :reserve-selection="true"
10 />
11 ...
12</el-table>
1getRowKey(row) {
2
3 return row.id
4},
5handleSelectionChange(selected) {
6 console.log('选中的数据list---', selected)
7},
二、el-table在ajax分页时支持单页全选和所有页全选
image.png
image.png
界面代码:
1 <el-table :data="tableData"
2 :height="tableHeight"
3 border
4 style=" 100%"
5 ref="table"
6 @selection-change="handleSelectionChange"
7 >
8 <el-table-column prop="id"
9 fixed
10 align="center">
11 <el-table-column type="selection"
12 width="75">
13 </el-table-column>
14 <template slot="header" slot-scope="scope">
15 <div>
16 <el-checkbox v-model="checkedAll"
17 @change="changeCheckAll">所有</el-checkbox>
18 </div>
19 </template>
20 </el-table-column>
21 ......
22 </el-table>
23 <pager :pager="pager"
24 @query="getList"
25 @setPager="onChangePage"></pager>
table上使用了ref属性,因为全选和反选时要用到dom操作方法toggleRowSelection,同样,表格自动铺满纵向屏幕时,也需要进行dom操作,这并非本节所讲内容,只是简单提一下,el-table并没有像layui中的table那样提供百分比-固定像素的方式响应式制定表格高度,我们得手动用js计算浏览器屏幕高度。
js部分代码如下:
1import pager from "@/components/table/Pager.vue";
2
3 export default {
4 components: {pager},
5 data () {
6 return {
7 checkedAll: false,
8 }
9 },
10 methods: {
11
12 handleSelectionChange (val) {
13 this.loading = val.length > 0 ? false : true;
14 this.multipleSelection = val;
15 },
16
17 toggleSelection (rows) {
18 if (rows) {
19 rows.forEach(row => {
20 this.$refs.table.toggleRowSelection(row);
21 });
22 } else {
23 this.$refs.table.clearSelection();
24 }
25 },
26
27 changeCheckAll (val) {
28 if (val) {
29
30 this.tableData.forEach(row => {
31 if (row) {
32 this.$refs.table.toggleRowSelection(row, true);
33 }
34 });
35 } else {
36 this.$refs.table.clearSelection();
37 }
38 },
39 }
40}
在每次点击“页码“之后,会自动执行查询方法,此时,如果点击了全选所有按钮,要在数据执行查询之后,再选中当前页面所有项,代码如下所示:
由于所有的dom操作要在dom渲染之后执行,所以使用了this.$nextTick()方法。
1 if(this.checkedAll){
2 this.$nextTick(()=>{
3 this.changeCheckAll(this.checkedAll);
4 })
5 }
在element-ui的Table组件当中,并没有提供给表头当中的复选框设置文本的属性和方法,我们可以通过使用css伪类来创建文本。
/deep/用于在css作用域当中进行样式透传,覆盖子组件的样式。
1/deep/ .el-table__header .el-table-column--selection .cell .el-checkbox:after {
2 content: "当页";
3 color: #606266;
4 font-weight: 500;
5 margin-left: 10px;
6 font-size: 14px;
7}
分页组件Pager.vue是对el-pagination组件的二次封装,其代码如下:
最重要的一点,就是所有页全选时的id集合,是每次查询时传递过来的,将其临时存储在data中,这样的话需要进行批量操作时,可以直接将这些id集合传递过去。当然,如果查询接口不把这些id集合带过来,我们也可以传一个所有页全选的标识给到后端,后端根据这个标识,重新去查询数据。
1 <template>
2 <div class="pagination-box clear">
3 <span class="page-total fl">
4 共有记录:
5 <span>{{ pager.total }}</span>条
6 </span>
7 <el-pagination
8 :small="small"
9 :layout="layout"
10 background
11 :pager-count="7"
12 :total="pager.total"
13 :current-page.sync="pager.pageNum"
14 :page-size="pager.pageSize"
15 :page-sizes="pageSize"
16 @size-change="onChangeSize"
17 @current-change="onChangePage"
18 ></el-pagination>
19 <span v-if="refresh" class="btn-refresh fn-right" title="刷新" @click="$emit('query')">
20 <i class="fas fa-redo"></i>
21 </span>
22 </div>
23</template>
24
25<script>
26export default {
27 name: "Pager",
28 props: {
29 small: {
30 type: Boolean,
31 default: false
32 },
33 layout: {
34 type: String,
35 default: "sizes,jumper, prev, pager, next"
36 },
37 pager: {
38 type: Object,
39 required: true
40 },
41 refresh: {
42 type: Boolean
43 },
44 pageSize: {
45 type: Array,
46 default: () => {
47 return [10, 15, 20, 50, 100, 200];
48 }
49 },
50 props: {
51 type: Object,
52 required: false,
53 default: () => ({
54 pageNum: "pageNum", // 第几页
55 pageSize: "pageSize", // 显示条数
56 total: "total" // 总记录条数
57 })
58 }
59 },
60 // 设置绑定参数
61 model: {
62 prop: "pager",
63 event: "setPager"
64 },
65 computed: {
66 total() {
67 return this.pager[this.props.total] || 0;
68 },
69 // 检测获取到的数据是否为空
70 isEmptyList() {
71 return (
72 Math.ceil(
73 this.pager[this.props.total] / this.pager[this.props.pageSize]
74 ) < this.pager[this.props.pageNum]
75 );
76 }
77 },
78 watch: {
79 total() {
80 // 存在记录但未获取到数据时, 重新请求
81 if (this.pager[this.props.pageNum] > 1 && this.isEmptyList) {
82 this.$emit(
83 "setPager",
84 Object.assign(this.pager, {
85 [this.props.pageNum]: this.pager[this.props.pageNum] - 1
86 })
87 );
88 this.$emit("query");
89 }
90 }
91 },
92 methods: {
93 // 每页条数
94 onChangeSize(pageSize) {
95 const temp = {
96 [this.props.pageSize]: pageSize,
97 // 当显示条数小于或等于总条数时,重置页数
98 [this.props.pageNum]:
99 pageSize <= this.total ? 1 : this.pager[this.props.pageNum]
100 };
101 this.$emit("setPager", Object.assign(this.pager, temp));
102 // 触发父组件查询请求
103 this.$emit("query");
104 },
105 // 翻页
106 onChangePage(pageNum) {
107 this.$emit(
108 "setPager",
109 Object.assign(this.pager, { [this.props.pageNum]: pageNum })
110 );
111 this.$emit("query");
112 }
113 }
114};
115</script>
116<style lang="scss" scoped>
117.pagination-box {
118 100%;
119 padding-top: 14px;
120 position: relative;
121 .el-pagination {
122 float: right;
123 }
124 /deep/ .el-pagination__sizes {
125 position: absolute;
126 top: 14px;
127 left: 150px !important;
128 }
129}
130.page-total {
131 padding-left: 20px;
132 height: 31px;
133 line-height: 31px;
134 font-size: 14px;
135 color: #838383;
136}
137
138.page-total span {
139 color: #3a3a3a;
140}
141
142.closeBtn {
143 text-align: center;
144 margin-top: 10px;
145}
146
147.el-input--small .el-input__inner {
148 height: 25px;
149 line-height: 25px;
150}
151
152.el-input__inner {
153 border-color: #838383;
154}
155.el-pagination .btn-next .el-icon,
156.el-pagination .btn-prev .el-icon {
157 font-size: 19px;
158 position: relative;
159 top: -3px;
160}
161.el-pager li {
162 margin: 0 8px;
163 border-radius: 3px;
164 height: 24px;
165 line-height: 24px;
166 min- 20px;
167}
168
169.el-pager li.active {
170 background: #1881bf !important;
171}
172
173.el-pagination__jump {
174 margin-right: 20px;
175 font-size: 14px;
176 color: #838383;
177}
178
179.el-pagination__jump .pagination__editor {
180 margin-right: 20px;
181}
182
183.el-pagination__jump .el-pagination__editor.el-input {
184 28px;
185}
186.el-pagination__jump .el-input__inner {
187 box-sizing: border-box;
188 100%;
189 color: #3a3a3a;
190 font-size: 14px;
191 border-color: #838383 !important;
192 height: 24px;
193 line-height: 24px;
194 border-radius: 3px;
195 background: #fff !important;
196}
197
198.el-pagination .el-select .el-input .el-input__inner {
199 border-radius: 15px !important;
200 font-size: 14px;
201 border-color: #838383 !important;
202 background: #fff !important;
203}
204.el-button--text > span > span {
205 color: #1881bf;
206 font-size: 12px;
207 text-decoration: underline;
208}
209</style>