feat(Tab): Add useAllTabStatus and replace useTabStatus (#13516)

This commit is contained in:
yuhengshen
2025-06-22 19:44:45 +08:00
committed by GitHub
parent da72797328
commit 1bd98c5265
6 changed files with 48 additions and 7 deletions

View File

@@ -1,6 +1,21 @@
import { inject, ComputedRef, InjectionKey } from 'vue';
import { inject, ComputedRef, InjectionKey, provide, computed } from 'vue';
// eslint-disable-next-line
export const TAB_STATUS_KEY: InjectionKey<ComputedRef<boolean>> = Symbol();
export const ALL_TAB_STATUS_KEY: InjectionKey<ComputedRef<boolean>> = Symbol();
export const useTabStatus = () => inject(TAB_STATUS_KEY, null);
export const useAllTabStatus = () => inject(ALL_TAB_STATUS_KEY, null);
export const useProvideTabStatus = (status: ComputedRef<boolean>) => {
const allTabStatus = useAllTabStatus();
provide(TAB_STATUS_KEY, status);
provide(
ALL_TAB_STATUS_KEY,
computed(() => {
return (allTabStatus == null || allTabStatus.value) && status.value;
}),
);
};

View File

@@ -22,7 +22,7 @@ import {
// Composables
import { useRect, useScrollParent, useEventListener } from '@vant/use';
import { useExpose } from '../composables/use-expose';
import { useTabStatus } from '../composables/use-tab-status';
import { useAllTabStatus } from '../composables/use-tab-status';
// Components
import { Loading } from '../loading';
@@ -60,7 +60,7 @@ export default defineComponent({
const loading = ref(props.loading);
const root = ref<HTMLElement>();
const placeholder = ref<HTMLElement>();
const tabStatus = useTabStatus();
const tabStatus = useAllTabStatus();
const scrollParent = useScrollParent(root);
const scroller = computed(() => props.scroller || scrollParent.value);

View File

@@ -385,3 +385,16 @@ For example, the following code:
```
This is because the `fixed` positioning inside the `transform` element is computed relative to that element, not relative to the entire document, resulting in layout exceptions.
### How to determine if the current component is inside an active Tab?
In a child component, you can use `useTabStatus` or `useAllTabStatus` to check whether the component is inside an active `Tab`.
- `useTabStatus`: Returns whether the current component's parent `Tab` is active. Returns `null` if the component is not inside a `Tab`.
- `useAllTabStatus`: In nested Tab scenarios, returns whether all parent `Tabs` are active. Returns `null` if the component is not inside a `Tab`.
```js
const isActive = useTabStatus();
// For nested Tab scenarios
const isAllActive = useAllTabStatus();
```

View File

@@ -423,3 +423,16 @@ this.$refs.tabs.resize();
```
这是因为 `transform` 元素内部的 `fixed` 定位会相对于该元素进行计算,而不是相对于整个文档,从而导致布局异常。
### 如何判断当前组件是否处于激活的 Tab 内?
可以在子组件中通过调用 `useTabStatus``useAllTabStatus` 来判断当前组件是否处于激活的 `Tab` 内部。
- `useTabStatus`:返回当前组件所在的 `Tab` 是否为激活状态,若组件不在 `Tab` 内部则返回 `null`
- `useAllTabStatus`:在存在嵌套 `Tab` 的场景下,返回是否所有上层 `Tab` 为激活状态,若组件不在 `Tab` 内部则返回 `null`
```js
const isActive = useTabStatus();
// 嵌套 Tab 场景
const isAllActive = useAllTabStatus();
```

View File

@@ -1,7 +1,6 @@
import {
ref,
watch,
provide,
computed,
nextTick,
watchEffect,
@@ -31,7 +30,7 @@ import { doubleRaf, useParent } from '@vant/use';
import { useId } from '../composables/use-id';
import { useExpose } from '../composables/use-expose';
import { routeProps } from '../composables/use-route';
import { TAB_STATUS_KEY } from '../composables/use-tab-status';
import { useProvideTabStatus } from '../composables/use-tab-status';
// Components
import { TabTitle } from './TabTitle';
@@ -154,7 +153,7 @@ export default defineComponent({
},
);
provide(TAB_STATUS_KEY, active);
useProvideTabStatus(active);
useExpose({
id,

View File

@@ -4,6 +4,7 @@ import _Tab from './Tab';
export const Tab = withInstall(_Tab);
export default Tab;
export { tabProps } from './Tab';
export { useTabStatus, useAllTabStatus } from '../composables/use-tab-status';
export type { TabProps } from './Tab';
declare module 'vue' {