vue: el-table initialization table selected item stepping pit record/element-ui form

Problem Description

First of all, the multi-selection function of element-ui table can refer to the official website example: multiple selection of table data ; manually select data in the table, and obtain the selected item by listening to selection-change, which is very smooth~
But when saving the options and reloading the table , hoping to "tick" the selected option but not showing the checked state at all:
No tick effect at all

debug process

$nextTick

first,Unresolved $nextTick! In many cases, the problem that the page display does not meet expectations after data manipulation can be solved by putting the data manipulation in the $nextTick callback! ! For specific principles, please refer to: In-depth analysis of $nextTick principles
. .

Initialize the selected item after the table data is loaded

After repeatedly stroking the logic of the dataTable component encapsulated by myself, I found that when the list of selected items sent by the parent component changes, it is likely that the table data has not been loaded yet! So actually the time to initialize the selected item should be inThe table data is loaded and the list of selected items of the parent is changedhour!
That is to say, it is necessary to monitor the table data and the parent selected item list at the same time (to monitor multiple properties at the same time, please refer to How does Vue watch monitor multiple properties at the same time? ), and the number of table data is not less than the number of selected items (the table data is loaded) and then Initialize selected items!

Check it out...Emm...But at least it's not completely unchecked now:
"Half" done
You can see that the specific data items still have no check box effect, but the full selection box on the header has a half selection effect!

The table selection must be a shallow copy of the table data

This miscellaneous fish has a guess, maybe there is a problem with the selected item list from the parent? So directly use slice to intercept the first three items of the form data to select, and found no problem! However, the selected item list data value passed from the parent is obviously exactly the same as the one intercepted by the slice, just to avoid the possible problems of object shallow copy (for the knowledge points of js deep copy and shallow copy, please refer to the difference between JavaScript deep copy and shallow copy), that is table data The new array obtained by deep copying...
hahaha! This time it is finally solved! Oh, I'm really dio★▽★

Reference Code

The el-table component dataTable packaged by this miscellaneous fish is posted here for reference only:
(There is also an interesting knowledge point, I strongly recommend those who don’t know it yet to take a look: vue transparent transmission )

<!-- 封装el-table -->
<template>
  <div id="DataTable">
    <div class="DataTable-table">
      <el-table :ref="tableKey" :data="tableData" v-bind="tableConfig" v-on="$listeners" height="100%"
        style="width: 100%;">
        <el-table-column v-if="showSelection" type="selection" width="48" align="center"></el-table-column>
        <el-table-column v-if="showNum" type="index" label="序号" width="80" align="center"></el-table-column>
        <slot>
          <el-table-column></el-table-column>
        </slot>
      </el-table>
    </div>
    <div v-if="showPagination" class="DataTable-pagination">
      <el-pagination v-bind="tableConfig" v-on="$listeners" :page-sizes="pageSizes" :layout="pagiLayout"
        :page-size.sync="query.pageSize" :total="total"></el-pagination>
    </div>
  </div>
</template>

<script>
	export default {
    
    
	  name: 'DataTable',
	  inheritAttrs: false, // 透传属性、事件
	  props: {
    
    
		tableKey: {
    
    
		  type: String,
		  default: () => 'dataTable'
		},
		// 表格配置
		showSelection: {
    
     // 是否显示多选框
		  type: Boolean,
		  default: false
		},
		showNum: {
    
     // 是否显示序号
		  type: Boolean,
		  default: true
		},
		selectItems: {
    
     // 选中项列表(必须是表格数据的浅拷贝)
		  type: Array,
		  default: () => []
		},
		// 分页栏配置
		showPagination: {
    
     // 是否显示分页栏
		  type: Boolean,
		  default: true
		},
		pageSizes: {
    
     // 分页大小
		  type: Array,
		  default: () => [10, 20, 50, 100]
		},
		pagiLayout: {
    
     // 分页栏布局配置
		  type: String,
		  default: () => 'total, prev, pager, next, sizes, jumper'
		}
	  },
	  data () {
    
    
			return {
    
    
				tableData: [],
				query: {
    
    
					pageSize: 10
				},
				total: 100
			}
	  },
	  computed: {
    
    
			tableConfig () {
    
     // 属性透传
				return {
    
    
					stripe: true, // 默认显示表格条纹
					...this.$attrs // 支持传过来的属性覆盖默认属性值
				}
			},
			initSelection () {
    
     // 当表格数据或选中项发生改变时,重新初始化表格选中项
				const {
    
     tableData, selectItems } = this
				return {
    
     tableData, selectItems }
			}
	  },
	  watch: {
    
    
			initSelection: {
    
    
				deep: true,
				immediate: true,
				handler (newVal) {
    
    
					const {
    
     tableData, selectItems } = newVal
					// 表格不支持选中数据、表格数据量少于选中的数据量(表格数据还没加载完)的情况下,不进行选中项初始化
					if(!this.showSelection || tableData.length < selectItems.length) return
					this.$nextTick(() => {
    
    
						this.toggleSelection(selectItems)
					})
				}
			}
	  },
	  mounted () {
    
    
	  },
	  methods: {
    
    
			dataChange () {
    
     // 数据发生改变时触发
				this.$emit('dataChange', this.tableData)
			},
			toggleSelection (selection) {
    
     // 切换给定列表项的选中状态
				if (selection) {
    
    
					this.$nextTick(() => {
    
    
						selection.forEach(row => {
    
    
							this.$refs[this.tableKey].toggleRowSelection(row)
						})
					})
				} else {
    
    
					this.clearSelection();
				}
			},
			clearSelection () {
    
     // 清除全部选中项
				this.$nextTick(() => {
    
    
					this.$refs[this.tableKey].clearSelection()
				})
			}
	  }
	}

</script>

<style lang="less" scoped>
	#DataTable {
    
    
		width: 100%;
		height: 100%;
		display: flex;
		flex-direction: column;
		overflow: hidden;

		.DataTable-table {
    
    
			flex: 1;
			overflow: auto;

			.el-table::before {
    
    
				background-color: transparent;
			}
		}
		
		.DataTable-pagination {
    
    
			position: relative;
			left: 0;
			bottom: 0;
			height: 42px;
			padding-top: 12px;
			display: flex;
			flex-direction: row-reverse;
		}
	}
</style>

Guess you like

Origin blog.csdn.net/qq_36604536/article/details/130820024
Recommended