fix(components): [tabs] set modelValue synchronously if beforeLeave is not set or is synchronous (#19387)

* fix: [tabs] sync modelValue if beforeLeave is not set or is synchronous

* feat: add unit test
This commit is contained in:
DDDDD12138 2025-01-06 23:37:17 +08:00 committed by GitHub
parent 536548e753
commit f6c9fd54ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 69 additions and 2 deletions

View File

@ -1,5 +1,5 @@
import { defineComponent, nextTick, ref } from 'vue'
import { mount } from '@vue/test-utils'
import { flushPromises, mount } from '@vue/test-utils'
import { describe, expect, test, vi } from 'vitest'
import { EVENT_CODE } from '@element-plus/constants'
import Tabs from '../src/tabs'
@ -777,4 +777,64 @@ describe('Tabs.vue', () => {
expect(panesWrapper.length).toBe(1)
})
test('set modelValue synchronously', async () => {
const handleTabClick = vi.fn()
const activeName = ref('tab1')
const wrapper = mount(() => (
<Tabs v-model={activeName.value} onTabClick={handleTabClick}>
<TabPane name="tab1" label="tab1">
Tab 1 content
</TabPane>
<TabPane name="tab2" label="tab2">
Tab 2 content
</TabPane>
</Tabs>
))
await nextTick()
const navWrapper = wrapper.findComponent(TabNav)
const navItemsWrapper = navWrapper.findAll('.el-tabs__item')
navItemsWrapper[1].trigger('click')
expect(activeName.value).toBe('tab2')
expect(handleTabClick).toHaveBeenCalledTimes(1)
})
test('set modelValue asynchronously using beforeLeave', async () => {
const handleTabClick = vi.fn()
const activeName = ref('tab1')
const beforeLeave = () => Promise.resolve(true)
const wrapper = mount(() => (
<Tabs
v-model={activeName.value}
onTabClick={handleTabClick}
beforeLeave={beforeLeave}
>
<TabPane name="tab1" label="tab1">
Tab 1 content
</TabPane>
<TabPane name="tab2" label="tab2">
Tab 2 content
</TabPane>
</Tabs>
))
await nextTick()
const navWrapper = wrapper.findComponent(TabNav)
const navItemsWrapper = navWrapper.findAll('.el-tabs__item')
navItemsWrapper[1].trigger('click')
expect(activeName.value).toBe('tab1')
expect(handleTabClick).toHaveBeenCalledTimes(1)
await flushPromises()
expect(activeName.value).toBe('tab2')
})
})

View File

@ -124,7 +124,14 @@ const Tabs = defineComponent({
if (currentName.value === value || isUndefined(value)) return
try {
const canLeave = await props.beforeLeave?.(value, currentName.value)
let canLeave
if (props.beforeLeave) {
const result = props.beforeLeave(value, currentName.value)
canLeave = result instanceof Promise ? await result : result
} else {
canLeave = true
}
if (canLeave !== false) {
currentName.value = value
if (trigger) {