diff --git a/packages/components/tabs/__tests__/tabs.test.ts b/packages/components/tabs/__tests__/tabs.test.ts index cdea0b82a4..b7b6484f83 100644 --- a/packages/components/tabs/__tests__/tabs.test.ts +++ b/packages/components/tabs/__tests__/tabs.test.ts @@ -678,4 +678,54 @@ describe('Tabs.vue', () => { test('resize', async () => { // TODO: jsdom not support `clientWidth`. }) + + test('DOM update finished calculating navOffset', async () => { + const tabs: string[] = [] + for (let i = 0; i < 5000; i++) { + tabs.push(i.toString()) + } + const wrapper = mount({ + components: { + 'el-tabs': Tabs, + 'el-tab-pane': TabPane, + }, + template: ` + + + + `, + data() { + return { + activeName: '0', + tabs, + } + }, + }) + + const tabsWrapper = wrapper.findComponent(Tabs) + await nextTick() + + const mockRect = vi + .spyOn(wrapper.find('#tab-4999').element, 'getBoundingClientRect') + .mockReturnValue({ left: 5000 } as DOMRect) + const mockComputedStyle = vi + .spyOn(window, 'getComputedStyle') + .mockReturnValue({ paddingLeft: '0px' } as CSSStyleDeclaration) + + await wrapper.find('#tab-4999').trigger('click') + await nextTick() + + expect(tabsWrapper.find('.el-tabs__active-bar').attributes().style).toMatch( + 'translateX(5000px)' + ) + + mockRect.mockRestore() + mockComputedStyle.mockRestore() + wrapper.unmount() + }) }) diff --git a/packages/components/tabs/src/tab-nav.tsx b/packages/components/tabs/src/tab-nav.tsx index f9d149aecd..f6aee18b23 100644 --- a/packages/components/tabs/src/tab-nav.tsx +++ b/packages/components/tabs/src/tab-nav.tsx @@ -3,6 +3,7 @@ import { defineComponent, getCurrentInstance, inject, + nextTick, onMounted, onUpdated, ref, @@ -135,10 +136,12 @@ const TabNav = defineComponent({ navOffset.value = newOffset } - const scrollToActiveTab = () => { + const scrollToActiveTab = async () => { const nav = nav$.value if (!scrollable.value || !el$.value || !navScroll$.value || !nav) return + await nextTick() + const activeTab = el$.value.querySelector('.is-active') if (!activeTab) return