一、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> 
个人笔记记录 2021 ~ 2025