fix(components): [table-column] column miss update due to key (#8528) (#10679)

* fix(components): [table-column] column miss update due to key (#8528)

* fix(components): [table-column] column miss update due to key (#8528)

* fix(components): [table-column] ts lint (#8528)

* fix(components): [table-column] column miss update due to key (#8528)

* fix(components): [table-column] states.updateOrderFns remove ref (#8528)

* fix(components): [table-column] add test for table (#8528)

* Update packages/components/table/src/store/watcher.ts

Co-authored-by: qiang <qw13131wang@gmail.com>

* fix(components): [table-column] fix ts define (#8528)

* fix(components): [table-column] column miss update due to key (#8528)

---------

Co-authored-by: qiang <qw13131wang@gmail.com>
This commit is contained in:
井柏然 2023-01-28 10:28:08 +08:00 committed by GitHub
parent 65a9cca1ed
commit 9721912342
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 110 additions and 4 deletions

View File

@ -1554,4 +1554,53 @@ describe('Table.vue', () => {
await doubleWait()
expect(wrapper.vm.selected.length).toEqual(3)
})
it('change columns order when use v-for & key to render table', async () => {
const wrapper = mount({
components: {
ElTable,
ElTableColumn,
},
template: `
<button class="change-column" @click="changeColumnData"></button>
<el-table :data="testData">
<el-table-column
v-for="item in columnsData"
:prop="item.prop"
:label="item.label"
:key="item.prop" />
</el-table>
`,
data() {
const testData = getTestData() as any
return {
testData,
columnsData: [
{ label: 'name', prop: 'name' },
{ label: 'release', prop: 'release' },
{ label: 'director', prop: 'director' },
{ label: 'runtime', prop: 'runtime' },
],
}
},
methods: {
changeColumnData() {
;[this.columnsData[0], this.columnsData[1]] = [
this.columnsData[1],
this.columnsData[0],
]
},
},
})
await doubleWait()
wrapper.find('.change-column').trigger('click')
await doubleWait()
expect(wrapper.find('.el-table__header').findAll('.cell')[0].text()).toBe(
'release'
)
expect(wrapper.find('.el-table__header').findAll('.cell')[1].text()).toBe(
'name'
)
})
})

View File

@ -73,7 +73,8 @@ function useStore<T>() {
insertColumn(
states: StoreStates,
column: TableColumnCtx<T>,
parent: TableColumnCtx<T>
parent: TableColumnCtx<T>,
updateColumnOrder: () => void
) {
const array = unref(states._columns)
let newColumns = []
@ -89,6 +90,7 @@ function useStore<T>() {
}
sortColumn(newColumns)
states._columns.value = newColumns
states.updateOrderFns.push(updateColumnOrder)
if (column.type === 'selection') {
states.selectable.value = column.selectable
states.reserveSelection.value = column.reserveSelection
@ -99,10 +101,22 @@ function useStore<T>() {
}
},
updateColumnOrder(states: StoreStates, column: TableColumnCtx<T>) {
const newColumnIndex = column.getColumnIndex?.()
if (newColumnIndex === column.no) return
sortColumn(states._columns.value)
if (instance.$ready) {
instance.store.updateColumns()
}
},
removeColumn(
states: StoreStates,
column: TableColumnCtx<T>,
parent: TableColumnCtx<T>
parent: TableColumnCtx<T>,
updateColumnOrder: () => void
) {
const array = unref(states._columns) || []
if (parent) {
@ -125,6 +139,9 @@ function useStore<T>() {
}
}
const updateFnIndex = states.updateOrderFns.indexOf(updateColumnOrder)
updateFnIndex > -1 && states.updateOrderFns.splice(updateFnIndex, 1)
if (instance.$ready) {
instance.store.updateColumns() // hack for dynamics remove column
instance.store.scheduleLayout()

View File

@ -60,6 +60,7 @@ function useWatcher<T>() {
const leafColumns: Ref<TableColumnCtx<T>[]> = ref([])
const fixedLeafColumns: Ref<TableColumnCtx<T>[]> = ref([])
const rightFixedLeafColumns: Ref<TableColumnCtx<T>[]> = ref([])
const updateOrderFns: (() => void)[] = []
const leafColumnsLength = ref(0)
const fixedLeafColumnsLength = ref(0)
const rightFixedLeafColumnsLength = ref(0)
@ -517,6 +518,7 @@ function useWatcher<T>() {
leafColumns,
fixedLeafColumns,
rightFixedLeafColumns,
updateOrderFns,
leafColumnsLength,
fixedLeafColumnsLength,
rightFixedLeafColumnsLength,

View File

@ -55,6 +55,7 @@ export default defineComponent({
getPropsData,
getColumnElIndex,
realAlign,
updateColumnOrder,
} = useRender(props as unknown as TableColumnCtx<unknown>, slots, owner)
const parent = columnOrTableParent.value
@ -140,14 +141,16 @@ export default defineComponent({
owner.value.store.commit(
'insertColumn',
columnConfig.value,
isSubColumn.value ? parent.columnConfig.value : null
isSubColumn.value ? parent.columnConfig.value : null,
updateColumnOrder
)
})
onBeforeUnmount(() => {
owner.value.store.commit(
'removeColumn',
columnConfig.value,
isSubColumn.value ? parent.columnConfig.value : null
isSubColumn.value ? parent.columnConfig.value : null,
updateColumnOrder
)
})
instance.columnId = columnId.value

View File

@ -189,6 +189,10 @@ function useRender<T>(
return Array.prototype.indexOf.call(children, child)
}
const updateColumnOrder = () => {
owner.value.store.commit('updateColumnOrder', instance.columnConfig.value)
}
return {
columnId,
realAlign,
@ -200,6 +204,7 @@ function useRender<T>(
setColumnRenders,
getPropsData,
getColumnElIndex,
updateColumnOrder,
}
}

View File

@ -157,6 +157,7 @@ import TableBody from './table-body'
import TableFooter from './table-footer'
import useUtils from './table/utils-helper'
import useStyle from './table/style-helper'
import useKeyRender from './table/key-render-helper'
import defaultProps from './table/defaults'
import { TABLE_INJECTION_KEY } from './tokens'
import { hColgroup } from './h-helper'
@ -272,6 +273,8 @@ export default defineComponent({
return props.emptyText || t('el.table.emptyText')
})
useKeyRender(table)
return {
ns,
layout,

View File

@ -0,0 +1,27 @@
import { onMounted, onUnmounted, ref } from 'vue'
import type { Table } from './defaults'
export default function useKeyRender(table: Table<[]>) {
const observer = ref<MutationObserver>()
const initWatchDom = () => {
const el = table.vnode.el
const columnsWrapper = (el as HTMLElement).querySelector('.hidden-columns')
const config = { childList: true, subtree: true }
const updateOrderFns = table.store.states.updateOrderFns
observer.value = new MutationObserver(() => {
updateOrderFns.forEach((fn: () => void) => fn())
})
observer.value.observe(columnsWrapper!, config)
}
onMounted(() => {
// fix https://github.com/element-plus/element-plus/issues/8528
initWatchDom()
})
onUnmounted(() => {
observer.value?.disconnect()
})
}