From c90ea234e8dfe86085a163dfe6cd82480d06c6d8 Mon Sep 17 00:00:00 2001 From: liuzaijiang <530604689@qq.com> Date: Thu, 27 Oct 2022 18:37:26 +0800 Subject: [PATCH] fix(comp:tabs): offset error when setting selectedKey --- packages/components/tabs/demo/Scroll.vue | 14 ++-- packages/components/tabs/src/InternalTabs.tsx | 68 ++++++++++++------- .../tabs/src/composables/useOffset.ts | 6 +- .../tabs/src/composables/useSize.ts | 21 +++--- 4 files changed, 65 insertions(+), 44 deletions(-) diff --git a/packages/components/tabs/demo/Scroll.vue b/packages/components/tabs/demo/Scroll.vue index ff76f5247..74cb716ba 100644 --- a/packages/components/tabs/demo/Scroll.vue +++ b/packages/components/tabs/demo/Scroll.vue @@ -13,7 +13,7 @@ Content of Tab {{ panel }} - addTab + addTab closeTab 移动到第几个: @@ -23,13 +23,17 @@ diff --git a/packages/components/tabs/src/InternalTabs.tsx b/packages/components/tabs/src/InternalTabs.tsx index de1f02180..c17329c45 100644 --- a/packages/components/tabs/src/InternalTabs.tsx +++ b/packages/components/tabs/src/InternalTabs.tsx @@ -89,14 +89,33 @@ export default defineComponent({ const [navOffset, setNavOffset] = useState(0) const [barStyle, setBarStyle] = useState({}) - const { navSize, navWrapperSize, navPreNextSize, selectedElSize, syncNavElSize, syncSelectedElSize } = - useNavRelatedElSize(isHorizontal, navWrapperElRef, navElRef, navPreElRef, selectedElRef) - const { selectedElOffset, syncSelectedElOffset } = useSelectedElOffset(isHorizontal, navPreNextSize, selectedElRef) + const { + navSize, + navWrapperSize, + navPreNextSize, + selectedElSize, + setNavElSize, + setSelectedElSize, + setNavPreNextElSize, + } = useNavRelatedElSize(isHorizontal, navWrapperElRef, navElRef, navPreElRef, selectedElRef) + const { selectedElOffset, setSelectedElOffset } = useSelectedElOffset(isHorizontal, navPreNextSize, selectedElRef) const hasScroll = computed(() => { - return navSize.value! > navWrapperSize.value + return navSize.value > navWrapperSize.value }) + watch( + hasScroll, + () => { + setNavPreNextElSize() + updateNavBarStyle() + updateSelectedOffset() + }, + { + flush: 'post', + }, + ) + const selectedElVisibleSize = useSelectedElVisibleSize(navWrapperSize, selectedElOffset, navOffset) // 处理存在滚动状态下,滚动到被选中的tab,并修正其位置 @@ -135,6 +154,14 @@ export default defineComponent({ }) }) + const navWrapperClass = computed(() => { + const prefixCls = mergedPrefixCls.value + return normalizeClass({ + [`${prefixCls}-nav-wrapper`]: true, + [`${prefixCls}-nav-wrapper-has-scroll`]: hasScroll.value, + }) + }) + const curryNavPreNextClasses = curry(useNavPreNextClasses)(props, mergedPrefixCls) const navPreClasses = curryNavPreNextClasses('pre', preReached) const navNextClasses = curryNavPreNextClasses('next', nextReached) @@ -203,9 +230,10 @@ export default defineComponent({ } const update = () => { - syncNavElSize() - syncSelectedElSize() - syncSelectedElOffset() + setNavElSize() + setNavPreNextElSize() + setSelectedElSize() + setSelectedElOffset() updateNavBarStyle() judgePreNextStatus() } @@ -239,19 +267,11 @@ export default defineComponent({ watch( navSize, - (val, oldSize) => { + (currentSize, oldSize) => { let offset = navOffset.value - const currentSize = val! - if (currentSize > oldSize && isAddTabs) { - offset += currentSize - oldSize - if (hasScroll.value) { - setNavOffset(offset) - } - } else if (currentSize < oldSize && !isAddTabs) { + if (currentSize < oldSize && !isAddTabs) { offset += currentSize - oldSize - if (offset >= 0) { - setNavOffset(offset) - } + setNavOffset(offset > 0 ? offset : 0) } }, { @@ -271,8 +291,9 @@ export default defineComponent({ watch( selectedElRef, () => { - syncSelectedElSize() - syncSelectedElOffset() + setSelectedElSize() + setSelectedElOffset() + setSelectedElOffset() updateSelectedOffset() updateNavBarStyle() }, @@ -305,12 +326,7 @@ export default defineComponent({ return (
-
+
{hasScroll.value && ( - syncSelectedElOffset: () => void + setSelectedElOffset: () => void } export function useSelectedElOffset( @@ -26,13 +26,13 @@ export function useSelectedElOffset( () => (isHorizontal.value ? selectedLeft.value : selectedTop.value) + navPreNextSize.value, ) - const syncSelectedElOffset = () => { + const setSelectedElOffset = () => { setSelectedLeft(selectedElRef.value?.offsetLeft ?? 0) setSelectedTop(selectedElRef.value?.offsetTop ?? 0) } return { selectedElOffset, - syncSelectedElOffset, + setSelectedElOffset, } } diff --git a/packages/components/tabs/src/composables/useSize.ts b/packages/components/tabs/src/composables/useSize.ts index b8bb1eb5d..a3dd481d4 100644 --- a/packages/components/tabs/src/composables/useSize.ts +++ b/packages/components/tabs/src/composables/useSize.ts @@ -7,7 +7,7 @@ import type { IconInstance } from '@idux/components/icon' -import { type ComputedRef, type Ref, computed, watchEffect } from 'vue' +import { type ComputedRef, type Ref, computed } from 'vue' import { useState } from '@idux/cdk/utils' @@ -16,8 +16,9 @@ export interface NavRelatedElSize { navWrapperSize: ComputedRef navPreNextSize: ComputedRef selectedElSize: ComputedRef - syncNavElSize: () => void - syncSelectedElSize: () => void + setNavElSize: () => void + setSelectedElSize: () => void + setNavPreNextElSize: () => void } export function useNavRelatedElSize( @@ -43,7 +44,7 @@ export function useNavRelatedElSize( const selectedElSize = computed(() => (isHorizontal.value ? selectedWidth.value : selectedHeight.value)) // dom 的size无法响应式获取,只能手动获取 - const syncNavElSize = () => { + const setNavElSize = () => { setNavWrapperWidth(navWrapperElRef.value?.offsetWidth ?? 0) setNavWrapperHeight(navWrapperElRef.value?.offsetHeight ?? 0) @@ -51,24 +52,24 @@ export function useNavRelatedElSize( setNavHeight(navElRef.value?.offsetHeight ?? 0) } - const syncSelectedElSize = () => { + const setSelectedElSize = () => { setSelectedWidth(selectedElRef.value?.offsetWidth ?? 0) setSelectedHeight(selectedElRef.value?.offsetHeight ?? 0) } - // 向前、向后按钮是动态渲染的,所以可以使用 watchEffect 获取其size - watchEffect(() => { + const setNavPreNextElSize = () => { setNavPreNextWidth(navPreElRef.value?.$el.offsetWidth ?? 0) setNavPreNextHeight(navPreElRef.value?.$el.offsetHeight ?? 0) - }) + } return { navSize, navWrapperSize, navPreNextSize, selectedElSize, - syncNavElSize, - syncSelectedElSize, + setNavElSize, + setSelectedElSize, + setNavPreNextElSize, } }