diff --git a/packages/components/table/__tests__/table.test.ts b/packages/components/table/__tests__/table.test.ts
index afa9d36ff2..31a34c5728 100644
--- a/packages/components/table/__tests__/table.test.ts
+++ b/packages/components/table/__tests__/table.test.ts
@@ -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: `
+
+
+
+
+ `,
+ 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'
+ )
+ })
})
diff --git a/packages/components/table/src/store/index.ts b/packages/components/table/src/store/index.ts
index 93e8f23453..fe8f2e9c76 100644
--- a/packages/components/table/src/store/index.ts
+++ b/packages/components/table/src/store/index.ts
@@ -73,7 +73,8 @@ function useStore() {
insertColumn(
states: StoreStates,
column: TableColumnCtx,
- parent: TableColumnCtx
+ parent: TableColumnCtx,
+ updateColumnOrder: () => void
) {
const array = unref(states._columns)
let newColumns = []
@@ -89,6 +90,7 @@ function useStore() {
}
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() {
}
},
+ updateColumnOrder(states: StoreStates, column: TableColumnCtx) {
+ const newColumnIndex = column.getColumnIndex?.()
+ if (newColumnIndex === column.no) return
+
+ sortColumn(states._columns.value)
+
+ if (instance.$ready) {
+ instance.store.updateColumns()
+ }
+ },
+
removeColumn(
states: StoreStates,
column: TableColumnCtx,
- parent: TableColumnCtx
+ parent: TableColumnCtx,
+ updateColumnOrder: () => void
) {
const array = unref(states._columns) || []
if (parent) {
@@ -125,6 +139,9 @@ function useStore() {
}
}
+ 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()
diff --git a/packages/components/table/src/store/watcher.ts b/packages/components/table/src/store/watcher.ts
index cf6ffdb3a0..e72a3f37f3 100644
--- a/packages/components/table/src/store/watcher.ts
+++ b/packages/components/table/src/store/watcher.ts
@@ -60,6 +60,7 @@ function useWatcher() {
const leafColumns: Ref[]> = ref([])
const fixedLeafColumns: Ref[]> = ref([])
const rightFixedLeafColumns: Ref[]> = ref([])
+ const updateOrderFns: (() => void)[] = []
const leafColumnsLength = ref(0)
const fixedLeafColumnsLength = ref(0)
const rightFixedLeafColumnsLength = ref(0)
@@ -517,6 +518,7 @@ function useWatcher() {
leafColumns,
fixedLeafColumns,
rightFixedLeafColumns,
+ updateOrderFns,
leafColumnsLength,
fixedLeafColumnsLength,
rightFixedLeafColumnsLength,
diff --git a/packages/components/table/src/table-column/index.ts b/packages/components/table/src/table-column/index.ts
index e4a5918fe5..d6dcac73d3 100644
--- a/packages/components/table/src/table-column/index.ts
+++ b/packages/components/table/src/table-column/index.ts
@@ -55,6 +55,7 @@ export default defineComponent({
getPropsData,
getColumnElIndex,
realAlign,
+ updateColumnOrder,
} = useRender(props as unknown as TableColumnCtx, 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
diff --git a/packages/components/table/src/table-column/render-helper.ts b/packages/components/table/src/table-column/render-helper.ts
index 17e39459a0..47efa804a3 100644
--- a/packages/components/table/src/table-column/render-helper.ts
+++ b/packages/components/table/src/table-column/render-helper.ts
@@ -189,6 +189,10 @@ function useRender(
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(
setColumnRenders,
getPropsData,
getColumnElIndex,
+ updateColumnOrder,
}
}
diff --git a/packages/components/table/src/table.vue b/packages/components/table/src/table.vue
index 08f602d94a..9d2f8a3adf 100644
--- a/packages/components/table/src/table.vue
+++ b/packages/components/table/src/table.vue
@@ -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,
diff --git a/packages/components/table/src/table/key-render-helper.ts b/packages/components/table/src/table/key-render-helper.ts
new file mode 100644
index 0000000000..6d8265091b
--- /dev/null
+++ b/packages/components/table/src/table/key-render-helper.ts
@@ -0,0 +1,27 @@
+import { onMounted, onUnmounted, ref } from 'vue'
+import type { Table } from './defaults'
+
+export default function useKeyRender(table: Table<[]>) {
+ const observer = ref()
+
+ 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()
+ })
+}