From a0135e8d51d5f6f615ac5f82f7afd98be4cd733e Mon Sep 17 00:00:00 2001 From: Eiinu Date: Tue, 2 Jul 2024 18:34:42 +0800 Subject: [PATCH] feat(tabbar): add prop before-switch (#3060) --- packages/nutui-eslint-config/index.js | 3 ++ .../src/nav/pages/tabbar/before-switch.vue | 41 +++++++++++++++++ .../src/nav/pages/tabbar/index.vue | 10 ++++- .../__snapshots__/index.spec.tsx.snap | 6 +-- .../__VUE/tabbar/__tests__/index.spec.tsx | 45 ++++++++++++++----- .../__VUE/tabbar/demo/before-switch.vue | 41 +++++++++++++++++ src/packages/__VUE/tabbar/demo/index.vue | 10 ++++- src/packages/__VUE/tabbar/doc.en-US.md | 14 +++++- src/packages/__VUE/tabbar/doc.md | 16 +++++-- src/packages/__VUE/tabbar/doc.taro.md | 16 +++++-- src/packages/__VUE/tabbar/tabbar.taro.vue | 20 +++++---- src/packages/__VUE/tabbar/tabbar.vue | 10 ++++- .../__VUE/tabbaritem/tabbar-item.taro.vue | 44 +++++++++--------- src/packages/__VUE/tabbaritem/tabbar-item.vue | 44 +++++++++--------- 14 files changed, 236 insertions(+), 84 deletions(-) create mode 100644 packages/nutui-taro-demo/src/nav/pages/tabbar/before-switch.vue create mode 100644 src/packages/__VUE/tabbar/demo/before-switch.vue diff --git a/packages/nutui-eslint-config/index.js b/packages/nutui-eslint-config/index.js index 6f541247fe..0c9564bc76 100644 --- a/packages/nutui-eslint-config/index.js +++ b/packages/nutui-eslint-config/index.js @@ -17,6 +17,9 @@ export default [ ...pluginVue.configs['flat/recommended'], { rules: { + 'no-empty': ['error', { + allowEmptyCatch: true + }], // typescript-eslint '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/ban-types': 'off', diff --git a/packages/nutui-taro-demo/src/nav/pages/tabbar/before-switch.vue b/packages/nutui-taro-demo/src/nav/pages/tabbar/before-switch.vue new file mode 100644 index 0000000000..c935a1fe11 --- /dev/null +++ b/packages/nutui-taro-demo/src/nav/pages/tabbar/before-switch.vue @@ -0,0 +1,41 @@ + + + diff --git a/packages/nutui-taro-demo/src/nav/pages/tabbar/index.vue b/packages/nutui-taro-demo/src/nav/pages/tabbar/index.vue index 419b5c0e73..ff0532fce9 100644 --- a/packages/nutui-taro-demo/src/nav/pages/tabbar/index.vue +++ b/packages/nutui-taro-demo/src/nav/pages/tabbar/index.vue @@ -21,6 +21,9 @@

{{ t('quantity') }}

+

{{ t('beforeSwitch') }}

+ +

{{ t('fixed') }}

@@ -36,6 +39,7 @@ import Badge from './badge.vue' import Color from './color.vue' import Quantity from './quantity.vue' import Fixed from './fixed.vue' +import BeforeSwitch from './before-switch.vue' const t = useTranslate({ 'zh-CN': { basic: '基础用法', @@ -45,7 +49,8 @@ const t = useTranslate({ badge: '徽标提示', color: '自定义颜色', quantity: '自定义数量', - fixed: '固定底部' + fixed: '固定底部', + beforeSwitch: '切换前的回调' }, 'en-US': { basic: 'Basic Usage', @@ -55,7 +60,8 @@ const t = useTranslate({ badge: 'Show Badge', color: 'Custom Color', quantity: 'Custom Quantity', - fixed: 'Fixed Bottom' + fixed: 'Fixed Bottom', + beforeSwitch: 'Before Switch' } }) diff --git a/src/packages/__VUE/tabbar/__tests__/__snapshots__/index.spec.tsx.snap b/src/packages/__VUE/tabbar/__tests__/__snapshots__/index.spec.tsx.snap index 11d8b1d3ac..cd0799abc6 100644 --- a/src/packages/__VUE/tabbar/__tests__/__snapshots__/index.spec.tsx.snap +++ b/src/packages/__VUE/tabbar/__tests__/__snapshots__/index.spec.tsx.snap @@ -1,18 +1,18 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`should render fixed element when using bottom prop 1`] = ` +exports[`Tabbar: should render fixed element when using bottom prop 1`] = ` "
" `; -exports[`should render placeholder when using placeholder and bottom prop 1`] = ` +exports[`Tabbar: should render placeholder when using placeholder and bottom prop 1`] = ` "
" `; -exports[`should render tabbar when default 1`] = ` +exports[`Tabbar: should render tabbar when default 1`] = ` "
diff --git a/src/packages/__VUE/tabbar/__tests__/index.spec.tsx b/src/packages/__VUE/tabbar/__tests__/index.spec.tsx index 8a2ac490f0..86024bf7ad 100644 --- a/src/packages/__VUE/tabbar/__tests__/index.spec.tsx +++ b/src/packages/__VUE/tabbar/__tests__/index.spec.tsx @@ -10,7 +10,7 @@ vi.mock('@/packages/utils/useRoute') push: vi.fn() }) -test('should render tabbar when default', async () => { +test('Tabbar: should render tabbar when default', async () => { const wrapper = mount(() => { return ( @@ -26,7 +26,7 @@ test('should render tabbar when default', async () => { expect(wrapper.html()).toMatchSnapshot() }) -test('should render custom img when using img prop', async () => { +test('Tabbar: should render custom img when using img prop', async () => { const wrapper = mount(() => { return ( @@ -63,7 +63,7 @@ test('should render custom img when using img prop', async () => { expect(tabbarItemIcon[1].element.src).toContain('c98ad61124172e93') }) -test('should render custom color and bage when using prop', async () => { +test('Tabbar: should render custom color and bage when using prop', async () => { const wrapper = mount(() => { return ( @@ -81,7 +81,7 @@ test('should render custom color and bage when using prop', async () => { expect(wrapper.find('.nut-badge').exists()).toBe(true) }) -test('should render fixed element when using bottom prop', async () => { +test('Tabbar: should render fixed element when using bottom prop', async () => { const wrapper = mount(Tabbar, { props: { bottom: true, @@ -90,7 +90,7 @@ test('should render fixed element when using bottom prop', async () => { }) expect(wrapper.html()).toMatchSnapshot() }) -test('should match active tabbar by clcik', async () => { +test('Tabbar: should match active tabbar by clcik', async () => { const wrapper = mount({ setup() { const active = ref(0) @@ -113,7 +113,7 @@ test('should match active tabbar by clcik', async () => { expect(tabbarItem[2].element.style.color).toEqual('blue') }) -test('should show sure emitted when click', async () => { +test('Tabbar: should show sure emitted when click', async () => { const tabSwitch = vi.fn() const wrapper = mount(() => { return ( @@ -130,7 +130,7 @@ test('should show sure emitted when click', async () => { expect(tabSwitch).toBeCalled() }) -test('should render placeholder when using placeholder and bottom prop', async () => { +test('Tabbar: should render placeholder when using placeholder and bottom prop', async () => { const wrapper = mount(Tabbar, { props: { bottom: true, @@ -142,7 +142,7 @@ test('should render placeholder when using placeholder and bottom prop', async ( expect(wrapper.html()).toMatchSnapshot() }) -test('should redirect when exist router and using to prop', async () => { +test('Tabbar: should redirect when exist router and using to prop', async () => { const wrapper = mount(() => { return ( @@ -158,7 +158,7 @@ test('should redirect when exist router and using to prop', async () => { expect(useRouter().push).toHaveBeenCalledWith('/category') }) -test('should call replace when no router exist and using to prop', async () => { +test('Tabbar: should call replace when no router exist and using to prop', async () => { (useRouter as any).mockReturnValue(undefined) const wrapper = mount(() => { @@ -176,7 +176,7 @@ test('should call replace when no router exist and using to prop', async () => { expect(location.replace).toHaveBeenCalledWith('/category') }) -test('should set window.location.href when using href prop', async () => { +test('Tabbar: should set window.location.href when using href prop', async () => { const wrapper = mount(() => { return ( @@ -190,3 +190,28 @@ test('should set window.location.href when using href prop', async () => { await tabbarItem[1].trigger('click') expect(window.location.href).toMatch('/category') }) + +test('Tabbar: props.beforeSwitch', async () => { + const val = ref(0) + const beforeSwitch = (_: any, index: string | number) => { + return Number(index) % 2 === 0 + } + const wrapper = mount(() => { + return ( + + + + + + ) + }) + const items = wrapper.findAll('.nut-tabbar-item') + expect(items.length).toBe(3) + items[2].trigger('click') + await nextTick() + expect(val.value).toBe(2) + + items[1].trigger('click') + await nextTick() + expect(val.value).toBe(2) +}) diff --git a/src/packages/__VUE/tabbar/demo/before-switch.vue b/src/packages/__VUE/tabbar/demo/before-switch.vue new file mode 100644 index 0000000000..5d35a52a40 --- /dev/null +++ b/src/packages/__VUE/tabbar/demo/before-switch.vue @@ -0,0 +1,41 @@ + + + diff --git a/src/packages/__VUE/tabbar/demo/index.vue b/src/packages/__VUE/tabbar/demo/index.vue index 5639473535..aebb5cf0aa 100644 --- a/src/packages/__VUE/tabbar/demo/index.vue +++ b/src/packages/__VUE/tabbar/demo/index.vue @@ -21,6 +21,9 @@

{{ t('quantity') }}

+

{{ t('beforeSwitch') }}

+ +

{{ t('fixed') }}

@@ -36,6 +39,7 @@ import Badge from './badge.vue' import Color from './color.vue' import Quantity from './quantity.vue' import Fixed from './fixed.vue' +import BeforeSwitch from './before-switch.vue' const t = useTranslate({ 'zh-CN': { basic: '基础用法', @@ -45,7 +49,8 @@ const t = useTranslate({ badge: '徽标提示', color: '自定义颜色', quantity: '自定义数量', - fixed: '固定底部' + fixed: '固定底部', + beforeSwitch: '切换前的回调' }, 'en-US': { basic: 'Basic Usage', @@ -55,7 +60,8 @@ const t = useTranslate({ badge: 'Show Badge', color: 'Custom Color', quantity: 'Custom Quantity', - fixed: 'Fixed Bottom' + fixed: 'Fixed Bottom', + beforeSwitch: 'Before Switch' } }) diff --git a/src/packages/__VUE/tabbar/doc.en-US.md b/src/packages/__VUE/tabbar/doc.en-US.md index ff4904e909..4a7482c89a 100644 --- a/src/packages/__VUE/tabbar/doc.en-US.md +++ b/src/packages/__VUE/tabbar/doc.en-US.md @@ -49,6 +49,10 @@ The bardge logo component is used internally and its properties can be applied d > demo: tabbar quantity +### Before Switch version + +> demo: tabbar before-switch + ### Fixed Bottom > demo: tabbar fixed @@ -59,12 +63,13 @@ The bardge logo component is used internally and its properties can be applied d | Attribute | Description | Type | Default | | --- | --- | --- | --- | -| v-model:visible | The index value of the selected label | number | `0` | +| v-model:visible | The index value of the selected label | string \| number | `0` | | bottom | Whether to fix the bottom | boolean | `false` | | unactive-color | Color of unactive tab item | string | `#7d7e80` | | active-color | Color of active tab item | string | `#1989fa` | | safe-area-inset-bottom | Whether to enable bottom safe area adaptation | boolean | `false` | | placeholder | Whether to generate a placeholder element when fixed | boolean | `false` | +| before-switch `version` | hook before switch event | `(data, value) => boolean \| Promise` | `() => true` | ### TabbarItem Props @@ -93,7 +98,12 @@ The bardge logo component is used internally and its properties can be applied d The component exports the following type definitions: ```js -import type { TabbarProps, TabbarInstance, TabbarItemProps, TabbarItemInstance } from '@nutui/nutui'; +import type { + TabbarProps, + TabbarInstance, + TabbarItemProps, + TabbarItemInstance +} from '@nutui/nutui'; ``` ## Theming diff --git a/src/packages/__VUE/tabbar/doc.md b/src/packages/__VUE/tabbar/doc.md index 059a995147..c58eafac82 100644 --- a/src/packages/__VUE/tabbar/doc.md +++ b/src/packages/__VUE/tabbar/doc.md @@ -49,7 +49,11 @@ app.use(TabbarItem) > demo: tabbar quantity -### 固定底部,可自由跳转 +### 切换前的回调 version + +> demo: tabbar before-switch + +### 固定底部 > demo: tabbar fixed @@ -59,12 +63,13 @@ app.use(TabbarItem) | 参数 | 说明 | 类型 | 默认值 | | --- | --- | --- | --- | -| v-model | 选中标签的索引值或者名称 | number | `0` | +| v-model | 选中标签的索引值或者名称 | string \| number | `0` | | bottom | 是否固定在页面底部 | boolean | `false` | | unactive-color | icon 未激活的颜色 | string | `#7d7e80` | | active-color | icon 激活的颜色 | string | `#1989fa` | | safe-area-inset-bottom | 是否开启 iphone 系列全面屏底部安全区适配 | boolean | `false` | | placeholder | 固定在底部时,是否在标签位置生成一个等高的占位元素 | boolean | `false` | +| before-switch `version` | 切换前的回调函数,返回 false 时拦截切换操作 | `(data, value) => boolean \| Promise` | `() => true` | ### TabbarItem Props @@ -93,7 +98,12 @@ app.use(TabbarItem) 组件导出以下类型定义: ```js -import type { TabbarProps, TabbarInstance, TabbarItemProps, TabbarItemInstance } from '@nutui/nutui'; +import type { + TabbarProps, + TabbarInstance, + TabbarItemProps, + TabbarItemInstance +} from '@nutui/nutui'; ``` ## 主题定制 diff --git a/src/packages/__VUE/tabbar/doc.taro.md b/src/packages/__VUE/tabbar/doc.taro.md index d6be732802..9044e940ba 100644 --- a/src/packages/__VUE/tabbar/doc.taro.md +++ b/src/packages/__VUE/tabbar/doc.taro.md @@ -49,7 +49,11 @@ app.use(TabbarItem) > demo: tabbar quantity nav -### 固定底部,可自由跳转 +### 切换前的回调 version + +> demo: tabbar before-switch nav + +### 固定底部 > demo: tabbar fixed nav @@ -59,12 +63,13 @@ app.use(TabbarItem) | 参数 | 说明 | 类型 | 默认值 | | --- | --- | --- | --- | -| v-model | 选中标签的索引值或者名称 | number | `0` | +| v-model | 选中标签的索引值或者名称 | string \| number | `0` | | bottom | 是否固定在页面底部 | boolean | `false` | | unactive-color | icon 未激活的颜色 | string | `#7d7e80` | | active-color | icon 激活的颜色 | string | `#1989fa` | | safe-area-inset-bottom | 是否开启 iphone 系列全面屏底部安全区适配 | boolean | `false` | | placeholder | 固定在底部时,是否在标签位置生成一个等高的占位元素 | boolean | `false` | +| before-switch `version` | 切换前的回调函数,返回 false 时拦截切换操作 | `(data, value) => boolean \| Promise` | `() => true` | ### TabbarItem Props @@ -91,7 +96,12 @@ app.use(TabbarItem) 组件导出以下类型定义: ```js -import type { TabbarProps, TabbarInstance, TabbarItemProps, TabbarItemInstance } from '@nutui/nutui-taro'; +import type { + TabbarProps, + TabbarInstance, + TabbarItemProps, + TabbarItemInstance +} from '@nutui/nutui-taro'; ``` ## 主题定制 diff --git a/src/packages/__VUE/tabbar/tabbar.taro.vue b/src/packages/__VUE/tabbar/tabbar.taro.vue index eb18ba1877..044056cfb6 100644 --- a/src/packages/__VUE/tabbar/tabbar.taro.vue +++ b/src/packages/__VUE/tabbar/tabbar.taro.vue @@ -1,11 +1,7 @@