From 75879999c1155db039917a8739ab3c46926a809c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E9=AD=94=E7=8E=8B?= <40223749+LYErin@users.noreply.github.com> Date: Fri, 29 Oct 2021 03:15:45 +0800 Subject: [PATCH] fix(tabs): refactor before-leave prop (#1420) * feat: update before-leave prop * fix: optimization * fix: update log * feat: update test * fix: add debug demo * feat: optimization * fix: add debug demo * feat: optimization * feat: optimization Co-authored-by: unknown --- CHANGELOG.en-US.md | 6 ++++ CHANGELOG.zh-CN.md | 6 ++++ src/tabs/src/Tab.tsx | 5 ++-- src/tabs/src/Tabs.tsx | 5 +++- src/tabs/src/interface.ts | 2 +- src/tabs/tests/Tabs.spec.tsx | 58 ++++++++++++++++++++++++++++++++++-- 6 files changed, 75 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index 1b9ee52e9..fef316aa2 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -1,5 +1,11 @@ # CHANGELOG +## Pending + +## Fixes + +- Fix `n-tabs` switch tab does not work when adding a new tab, closes [#1417](https://github.com/TuSimple/naive-ui/issues/1417). + ## 2.20.0 (2021-10-28) ### Breaking Changes diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index 91367af84..3c224cf38 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -1,5 +1,11 @@ # CHANGELOG +## Pending + +## Fixes + +- 修复 `n-tabs` 在新增 tab 后切换 tab 无法生效,关闭 [#1417]https://github.com/TuSimple/naive-ui/issues/1417) + ## 2.20.0 (2021-10-28) ### Breaking Changes diff --git a/src/tabs/src/Tab.tsx b/src/tabs/src/Tab.tsx index 2e5d45d16..d6cd8c297 100644 --- a/src/tabs/src/Tab.tsx +++ b/src/tabs/src/Tab.tsx @@ -51,9 +51,8 @@ export default defineComponent({ return } const { name: nameProp } = props + const id = ++nextTabNameRef.id if (nameProp !== valueRef.value) { - if (nameProp === nextTabNameRef.value) return - nextTabNameRef.value = nameProp const { value: onBeforeLeave } = onBeforeLeaveRef if (!onBeforeLeave) { handleTabClick(nameProp) @@ -61,7 +60,7 @@ export default defineComponent({ void Promise.resolve( (onBeforeLeave as OnBeforeLeaveImpl)(props.name, valueRef.value) ).then((allowLeave) => { - if (allowLeave) { + if (allowLeave && nextTabNameRef.id === id) { handleTabClick(nameProp) } }) diff --git a/src/tabs/src/Tabs.tsx b/src/tabs/src/Tabs.tsx index f378c5223..10df76fd9 100644 --- a/src/tabs/src/Tabs.tsx +++ b/src/tabs/src/Tabs.tsx @@ -144,7 +144,10 @@ export default defineComponent({ uncontrolledValueRef ) - const nextTabNameRef = { value: mergedValueRef.value } + const nextTabNameRef = { id: 0 } + watch(mergedValueRef, () => { + nextTabNameRef.id = 0 + }) const tabWrapperStyleRef = computed(() => { if (!props.justifyContent || props.type === 'card') return undefined diff --git a/src/tabs/src/interface.ts b/src/tabs/src/interface.ts index 54afef99b..1f0dde6bb 100644 --- a/src/tabs/src/interface.ts +++ b/src/tabs/src/interface.ts @@ -24,7 +24,7 @@ export interface TabsInjection { closableRef: Ref tabStyleRef: Ref paneStyleRef: Ref - nextTabNameRef: { value: string | number | null } + nextTabNameRef: { id: number } onBeforeLeaveRef: Ref handleTabClick: (panelName: string | number) => void handleClose: (panelName: string | number) => void diff --git a/src/tabs/tests/Tabs.spec.tsx b/src/tabs/tests/Tabs.spec.tsx index 08a537a5e..7364965ee 100644 --- a/src/tabs/tests/Tabs.spec.tsx +++ b/src/tabs/tests/Tabs.spec.tsx @@ -2,6 +2,7 @@ import { mount } from '@vue/test-utils' import { h } from 'vue' import { NTabPane, NTabs } from '../index' import { AddIcon } from '../../_internal/icons' +import { sleep } from 'seemly' describe('n-tabs', () => { it('should work with import on demand', () => { @@ -42,15 +43,20 @@ describe('n-tabs', () => { }) }) - it('should show AddIcon with `addable` prop', () => { + it('should show AddIcon with `addable` prop', async () => { + const onAdd = jest.fn() const wrapper = mount(NTabs, { props: { type: 'card', - addable: true + addable: true, + onAdd } }) expect(wrapper.findComponent(AddIcon).exists()).toBe(true) + const addIcon = wrapper.find('.n-tabs-tab--addable') + await addIcon.trigger('click') + expect(onAdd).toHaveBeenCalled() }) it('should work with `justify-content` prop', async () => { @@ -136,4 +142,52 @@ describe('n-tabs', () => { expect(wrapper.find('.test-if').exists()).toEqual(false) expect(wrapper.find('.test-show-lazy').exists()).toEqual(true) }) + + it('should work with `on-before-leave` prop', async () => { + const wrapper = mount(NTabs, { + props: { + type: 'card', + defaultValue: '3', + onBeforeLeave: (name: string) => { + switch (name) { + case '1': + return false + case '2': + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion + return new Promise((resolve) => { + setTimeout(() => { + resolve(true) + }, 1000) + }) as Promise + default: + return true + } + } + }, + slots: { + default: () => [ + h(NTabPane, { + tab: '1', + name: '1' + }), + h(NTabPane, { + tab: '2', + name: '2' + }), + h(NTabPane, { + tab: '3', + name: '3' + }) + ] + } + }) + const tabs = wrapper.findAll('.n-tabs-tab') + expect(tabs[2].classes()).toContain('n-tabs-tab--active') + await tabs[0].trigger('click') + expect(tabs[2].classes()).toContain('n-tabs-tab--active') + await tabs[1].trigger('click') + expect(tabs[2].classes()).toContain('n-tabs-tab--active') + await sleep(1000) + expect(tabs[1].classes()).toContain('n-tabs-tab--active') + }) })