From 1f17383592be7917a3f8392025ada60c788738f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E9=BB=84=E6=B1=AA?= <50308467+huangguang1999@users.noreply.github.com> Date: Fri, 1 Mar 2024 18:43:18 +0800 Subject: [PATCH] fix: `Tabs` tab-cell support "updateLayout" method (#234) --- .../__test__/__snapshots__/index.spec.js.snap | 116 ++++++++++++++++++ .../components/tabs/__test__/index.spec.js | 5 +- .../arcodesign/components/tabs/demo/resize.md | 68 ++++++++++ .../arcodesign/components/tabs/tab-cell.tsx | 66 ++++++---- packages/arcodesign/components/tabs/type.ts | 5 + 5 files changed, 234 insertions(+), 26 deletions(-) create mode 100644 packages/arcodesign/components/tabs/demo/resize.md diff --git a/packages/arcodesign/components/tabs/__test__/__snapshots__/index.spec.js.snap b/packages/arcodesign/components/tabs/__test__/__snapshots__/index.spec.js.snap index 39d1084b..22e7e0c8 100644 --- a/packages/arcodesign/components/tabs/__test__/__snapshots__/index.spec.js.snap +++ b/packages/arcodesign/components/tabs/__test__/__snapshots__/index.spec.js.snap @@ -717,6 +717,122 @@ exports[`tabs demo test tabs demo: extra.md renders correctly 1`] = ` `; +exports[`tabs demo test tabs demo: resize.md renders correctly 1`] = ` + + +
+
+
+
+
+ Example1 +
+
+ Example2 +
+
+ Example3 +
+
+ Example4 +
+
+ Example5 +
+
+ Example6 +
+
+ Example7 +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Content area +
+
+
+
+
+
+
+ +`; + exports[`tabs demo test tabs demo: scroll.md renders correctly 1`] = `
{ expect(onChange.mock.calls).toHaveLength(1); expect(onChange.mock.calls[0]).toEqual([{ title: 'Title 2' }, 1, 'scroll']); const onScroll = jest.fn(); - const { scrollToIndex } = ref.current; + const { scrollToIndex, bar } = ref.current; + const { updateLayout } = bar || {}; expect(typeof scrollToIndex).toBe('function'); + expect(typeof updateLayout).toBe('function'); // wrapper.setProps({ onScroll }); scrollToIndex(0); + updateLayout(); // wrapper.update(); // expect(onScroll.mock.calls).toHaveLength(1); }); diff --git a/packages/arcodesign/components/tabs/demo/resize.md b/packages/arcodesign/components/tabs/demo/resize.md new file mode 100644 index 00000000..3bf2af2a --- /dev/null +++ b/packages/arcodesign/components/tabs/demo/resize.md @@ -0,0 +1,68 @@ +## font-size 改变需要重新 rerender tab-cell @en{Font-size changes require rerendering tab-cell} + +#### 12 + +```js +import { Tabs, Button } from '@arco-design/mobile-react'; + +const tabData = [ + { title: 'Example1' }, + { title: 'Example2' }, + { title: 'Example3' }, + { title: 'Example4' }, + { title: 'Example5' }, + { title: 'Example6' }, + { title: 'Example7' }, +]; + +export default function TabsDemo() { + const theRef = React.useRef(); + const handleClick = () => { + if (theRef.current) { + var divNodes = theRef.current.bar.dom.getElementsByTagName("div"); + for (var i = 0; i < divNodes.length; i++) { + divNodes[i].setAttribute("style", "font-size: 32px!important;"); + } + setTimeout(() => { + theRef.current.bar.updateLayout(); + }, 20) + } + } + return ( + <> + + { + console.log('[tabs]', tab, index); + }} + translateZ={false} + tabBarHasDivider={false} + > +
Content area
+
Content area
+
Content area
+
Content area
+
Content area
+
Content area
+
Content area
+
+ + ); +} +``` + +```less +.demo-tab-content { + display: flex; + align-items: center; + justify-content: center; + .rem(font-size, 15); + .rem(height, 80); + .use-var(color, sub-info-font-color); +} +``` diff --git a/packages/arcodesign/components/tabs/tab-cell.tsx b/packages/arcodesign/components/tabs/tab-cell.tsx index e063d824..c6907e13 100644 --- a/packages/arcodesign/components/tabs/tab-cell.tsx +++ b/packages/arcodesign/components/tabs/tab-cell.tsx @@ -73,6 +73,7 @@ const TabCell = forwardRef((props: TabCellProps, ref: Ref) => { const [originArrange, setOriginArrange] = useState(() => tabs.length < overflowThreshold ? tabBarArrange : 'start', ); + const [forceUpdate, setForceUpdate] = useState(false); // 默认tab小于overflowThreshold个时不开启加载前隐藏,大于overflowThreshold个时开启 const [showTab, setShowTab] = useState(() => hideTabBarBeforeMounted === void 0 @@ -93,6 +94,19 @@ const TabCell = forwardRef((props: TabCellProps, ref: Ref) => { const system = useSystem(); + const updateScrollPosition = () => { + if (wrapSize && tabBarScrollChance !== 'none') { + setTimeout( + () => { + scrollToCenter(); + }, + tabBarScrollChance === 'after-jump' + ? Math.max(transitionDuration || 0, duration || 0) + : 0, + ); + } + }; + useEffect(() => { nextTick(() => { setCellOverflow(); @@ -119,32 +133,16 @@ const TabCell = forwardRef((props: TabCellProps, ref: Ref) => { tabDirection, ]); - useImperativeHandle( - ref, - () => ({ - dom: domRef.current, - scrollTo, - scrollToCenter, - hasOverflow, - setCaterpillarAnimate: ratio => underlineRef.current?.setCaterpillarAnimate(ratio), - resetUnderlineStyle: () => underlineRef.current?.resetUnderlineStyle(), - }), - [scrollToCenter, scrollTo, hasOverflow], - ); - useEffect(() => { - if (wrapSize && tabBarScrollChance !== 'none') { - setTimeout( - () => { - scrollToCenter(); - }, - tabBarScrollChance === 'after-jump' - ? Math.max(transitionDuration || 0, duration || 0) - : 0, - ); - } + updateScrollPosition(); }, [activeIndex, wrapSize]); + useEffect(() => { + setCellOverflow(); + underlineRef.current?.resetUnderlineStyle(); + updateScrollPosition(); + }, [forceUpdate]); + useEffect(() => { tabBarScrollChance !== 'none' && scrollToCenter(true); // TabCell左右可滚动时,防止触发父级touchmove事件导致滚不动 @@ -275,7 +273,7 @@ const TabCell = forwardRef((props: TabCellProps, ref: Ref) => { return typeof tab === 'string' ? tab : tab.title; } - function renderTabUnderline() { + const renderTabUnderline = () => { if (!showUnderline || !isLine) { return null; } @@ -308,7 +306,7 @@ const TabCell = forwardRef((props: TabCellProps, ref: Ref) => { {...lineProps} /> ); - } + }; const cellInner = ( <> @@ -360,6 +358,24 @@ const TabCell = forwardRef((props: TabCellProps, ref: Ref) => { ); + const updateLayout = () => { + setForceUpdate(!forceUpdate); + }; + + useImperativeHandle( + ref, + () => ({ + dom: domRef.current, + scrollTo, + scrollToCenter, + hasOverflow, + setCaterpillarAnimate: ratio => underlineRef.current?.setCaterpillarAnimate(ratio), + resetUnderlineStyle: () => underlineRef.current?.resetUnderlineStyle(), + updateLayout: () => updateLayout(), + }), + [scrollToCenter, scrollTo, hasOverflow], + ); + return (
void; + /** + * 强制更新 tab-cell + * @en Force update tab-cell + */ + updateLayout: () => void; } export interface TabPaneProps