From e44cec79d1115d83b3e016e96eed8634c8bb4325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Fri, 5 May 2023 10:05:53 +0800 Subject: [PATCH 01/23] chore: bump version 5.30.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f7f5744d25..63cd7831d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "antd-mobile", - "version": "5.29.1", + "version": "5.30.0", "scripts": { "start": "dumi dev", "build": "gulp", From ad72739f9b03fe9f5e4d194e507747c4fed55a8d Mon Sep 17 00:00:00 2001 From: "Lex.Chen" Date: Tue, 9 May 2023 13:55:26 +0800 Subject: [PATCH 02/23] Update Qcode of DingTalk group in README.md (#6148) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7574ef118f..74bdcf6f04 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ · Discord · - 钉钉 + 钉钉 From dfbd416cff0708c37deb50f093ea07d0d97f15b8 Mon Sep 17 00:00:00 2001 From: season Date: Wed, 10 May 2023 11:02:54 +0800 Subject: [PATCH 03/23] docs: update the description of the css-variables.zh/en.md (#6152) Co-authored-by: canwin\vans <2313219475@qq.com> --- docs/guide/css-variables.en.md | 2 +- docs/guide/css-variables.zh.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guide/css-variables.en.md b/docs/guide/css-variables.en.md index 191cd9d0c6..b169d7e1c9 100644 --- a/docs/guide/css-variables.en.md +++ b/docs/guide/css-variables.en.md @@ -21,7 +21,7 @@ Next, we need to set the value of the CSS variable. There are two ways: ### Method 1: Set in the CSS file -Add a custom `className` to the Input component: +Add a custom `className` to the Button component: ```jsx ) - fireEvent.click(screen.getByText('show')) await screen.findAllByRole('img') const slides = document.querySelectorAll(`.${classPrefix}-slides`)[0] expect(screen.getByText('1 / 4')).toBeInTheDocument() - mockDrag(slides, [ - { - clientX: 300, - }, - { - clientX: 200, - }, - { - clientX: 100, - }, - ]) - await waitFor(() => expect(onIndexChange).toBeCalledWith(1)) + await act(async () => { + await mockDrag( + slides, + [ + { + clientX: 300, + }, + { + clientX: 200, + }, + { + clientX: 100, + }, + ], + 5 + ) + }) + + expect(onIndexChange).toBeCalledWith(1) expect(screen.getByText('2 / 4')).toBeInTheDocument() }) }) diff --git a/src/components/passcode-input/tests/passcode-input.test.tsx b/src/components/passcode-input/tests/passcode-input.test.tsx index 31261ca825..ccd8e66020 100644 --- a/src/components/passcode-input/tests/passcode-input.test.tsx +++ b/src/components/passcode-input/tests/passcode-input.test.tsx @@ -69,7 +69,9 @@ describe('PasscodeInput', () => { render() const input = screen.getByRole('button', { name: '密码输入框' }) fireEvent.focus(input) - await userEvent.keyboard('abc') + await act(async () => { + await userEvent.keyboard('abc') + }) expect(input).toHaveTextContent('abc') }) @@ -91,7 +93,9 @@ describe('PasscodeInput', () => { const input = screen.getByRole('button', { name: '密码输入框' }) fireEvent.focus(input) expect(onFocus).toBeCalled() - await userEvent.keyboard('abcde') + await act(async () => { + await userEvent.keyboard('abcde') + }) expect(onFill).toBeCalled() expect(onChange).toBeCalledTimes(4) fireEvent.blur(input) diff --git a/src/components/popup/tests/popup.test.tsx b/src/components/popup/tests/popup.test.tsx index 549cf9baf0..6565beb1f5 100644 --- a/src/components/popup/tests/popup.test.tsx +++ b/src/components/popup/tests/popup.test.tsx @@ -1,9 +1,9 @@ import * as React from 'react' -import { render, mockDrag } from 'testing' +import { render, mockDrag, act, waitFor } from 'testing' import Popup from '..' describe('Popup', () => { - test('top swipe should be closed', () => { + test('top swipe should be closed', async () => { const onClose = jest.fn() render( @@ -11,19 +11,19 @@ describe('Popup', () => { ) - mockDrag( + await mockDrag( document.querySelector('.adm-popup') as Element, - new Array(8).fill(0).map((_, i) => { + new Array(4).fill(0).map((_, i) => { return { clientY: 400 - 50 * i, } - }) + }), + 5 ) - expect(onClose).toBeCalledTimes(1) }) - test('bottom swipe should be closed', () => { + test('bottom swipe should be closed', async () => { const onClose = jest.fn() render( @@ -31,15 +31,15 @@ describe('Popup', () => { ) - mockDrag( + await mockDrag( document.querySelector('.adm-popup') as Element, - new Array(8).fill(0).map((_, i) => { + new Array(6).fill(0).map((_, i) => { return { clientY: 50 * i, } - }) + }), + 5 ) - expect(onClose).toBeCalledTimes(1) }) }) diff --git a/src/components/radio/tests/radio.test.tsx b/src/components/radio/tests/radio.test.tsx index 40e8d99920..fa3b56fed1 100644 --- a/src/components/radio/tests/radio.test.tsx +++ b/src/components/radio/tests/radio.test.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { fireEvent, render, testA11y, userEvent, screen } from 'testing' +import { fireEvent, render, testA11y, userEvent, screen, act } from 'testing' import Radio from '../' import { RadioGroupProps } from '../group' @@ -30,7 +30,10 @@ describe('Radio', () => { 1 ) - await userEvent.tripleClick(screen.getByRole('radio')) + + await act(async () => { + await userEvent.tripleClick(screen.getByRole('radio')) + }) expect(onChange).toBeCalledTimes(1) }) }) @@ -125,7 +128,9 @@ describe('Radio.Group', () => { 2 ) - await userEvent.tripleClick(screen.getByRole('radio', { name: '1' })) + await act(async () => { + await userEvent.tripleClick(screen.getByRole('radio', { name: '1' })) + }) expect(onChange).toBeCalledTimes(1) }) }) diff --git a/src/components/search-bar/tests/search-bar.test.tsx b/src/components/search-bar/tests/search-bar.test.tsx index f68cf4e11e..53543ed29c 100644 --- a/src/components/search-bar/tests/search-bar.test.tsx +++ b/src/components/search-bar/tests/search-bar.test.tsx @@ -53,7 +53,9 @@ describe('adm-search-bar', () => { render() const input = screen.getByRole('searchbox') fireEvent.focus(input) - await userEvent.type(input, '12') + await act(async () => { + await userEvent.type(input, '12') + }) fireEvent.click(screen.getByText('取消')) expect(input).toHaveValue('') }) @@ -62,7 +64,9 @@ describe('adm-search-bar', () => { const onSearch = jest.fn() render() const input = screen.getByRole('searchbox') - await userEvent.type(input, '12{enter}') + await act(async () => { + await userEvent.type(input, '12{enter}') + }) expect(onSearch).toBeCalledWith('12') }) @@ -80,7 +84,10 @@ describe('adm-search-bar', () => { expect(input).toHaveFocus() expect(onFocus).toBeCalled() - await userEvent.type(input, '12') + await act(async () => { + await userEvent.type(input, '12') + }) + act(() => { ref.current?.clear() }) diff --git a/src/components/swiper/tests/swiper.test.tsx b/src/components/swiper/tests/swiper.test.tsx index a9b3298bdb..ded1fa445b 100644 --- a/src/components/swiper/tests/swiper.test.tsx +++ b/src/components/swiper/tests/swiper.test.tsx @@ -237,17 +237,21 @@ describe('Swiper', () => { ) const el = $$(`.${classPrefix}-track`)[0] - mockDrag(el, [ - { clientX: 50, clientY: 300 }, - { - clientX: 50, - clientY: 200, - }, - { - clientX: 60, - clientY: 50, - }, - ]) + await mockDrag( + el, + [ + { clientX: 50, clientY: 300 }, + { + clientX: 50, + clientY: 200, + }, + { + clientX: 60, + clientY: 50, + }, + ], + 5 + ) expect($$(`.${classPrefix}-track-inner`)[0]).toHaveStyle( 'transform: translate3d(0,-100%,0)' diff --git a/src/tests/testing.tsx b/src/tests/testing.tsx index d3d59cac12..06c5916e7c 100644 --- a/src/tests/testing.tsx +++ b/src/tests/testing.tsx @@ -104,7 +104,7 @@ export { customRender as render } export const testA11y = async (ui: UI | Element) => { const container = React.isValidElement(ui) ? customRender(ui).container : ui - const results = await axe(container) + const results = await axe(container as Element) expect(results).toHaveNoViolations() } @@ -116,7 +116,7 @@ export const actSleep = (time: number) => { return act(() => sleep(time)) } -export const mockDrag = (el: Element, options: any[]) => { +export const mockDrag = async (el: Element, options: any[], time?: number) => { const [downOptions, ...moveOptions] = options fireEvent.mouseDown(el, { buttons: 1, @@ -127,6 +127,10 @@ export const mockDrag = (el: Element, options: any[]) => { buttons: 1, ...item, }) + + if (time) { + await sleep(time) + } } fireEvent.mouseUp(el) } From 04a59db3078340e168f88d5015b3a13775486233 Mon Sep 17 00:00:00 2001 From: miracles1919 <516571350@qq.com> Date: Tue, 27 Jun 2023 10:42:40 +0800 Subject: [PATCH 19/23] fix(Input): fix the display issue of numbers starting with 0 (#6217) --- src/components/input/input.tsx | 6 +++++- src/components/input/tests/input.test.tsx | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/components/input/input.tsx b/src/components/input/input.tsx index 9d2a9a3159..0ab19f3d06 100644 --- a/src/components/input/input.tsx +++ b/src/components/input/input.tsx @@ -121,9 +121,13 @@ export const Input = forwardRef((p, ref) => { function checkValue() { let nextValue = value if (props.type === 'number') { - nextValue = + const boundValue = nextValue && bound(parseFloat(nextValue), props.min, props.max).toString() + // fix the display issue of numbers starting with 0 + if (Number(nextValue) !== Number(boundValue)) { + nextValue = boundValue + } } if (nextValue !== value) { setValue(nextValue) diff --git a/src/components/input/tests/input.test.tsx b/src/components/input/tests/input.test.tsx index c6373bee4b..46fee22293 100644 --- a/src/components/input/tests/input.test.tsx +++ b/src/components/input/tests/input.test.tsx @@ -190,4 +190,22 @@ describe('Input', () => { }) expect(ref.current?.nativeElement?.value).toBe('') }) + + test('numbers that start with 0 should be work', () => { + const ref = createRef() + render() + const input = document.querySelector('input')! + fireEvent.change(input, { + target: { value: '012' }, + }) + // input.blur() + act(() => { + input.focus() + }) + act(() => { + input.blur() + }) + + expect(input.value).toBe('012') + }) }) From a11e8529c63d9d6f6bcd173be15142e863040ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=90=86=E5=A1=98=E7=9A=84=E5=B8=8C=E6=9C=9B?= <1587315093@qq.com> Date: Tue, 27 Jun 2023 11:18:32 +0800 Subject: [PATCH 20/23] doc: update TabBar name (#6219) --- src/components/tab-bar/index.en.md | 2 +- src/components/tab-bar/index.zh.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/tab-bar/index.en.md b/src/components/tab-bar/index.en.md index 7c4fff5d4c..22990e7dc9 100644 --- a/src/components/tab-bar/index.en.md +++ b/src/components/tab-bar/index.en.md @@ -19,7 +19,7 @@ Useful for switching between different pages. | Name | Description | Type | Default | | --- | --- | --- | --- | | activeKey | `key` of currently active `item` | `string \| null` | - | -| defaultActiveKey | The initialized `key` of the selected `item`, if the `activeKey` is not set | `string \| null` | `key` of the 1st `Tab` | +| defaultActiveKey | The initialized `key` of the selected `item`, if the `activeKey` is not set | `string \| null` | `key` of the first `TabBar.Item` | | onChange | Callback when switching panel | `(key: string) => void` | - | | safeArea | Whether to enable safe area padding | `boolean` | `false` | diff --git a/src/components/tab-bar/index.zh.md b/src/components/tab-bar/index.zh.md index 90112ec71c..54032233bb 100644 --- a/src/components/tab-bar/index.zh.md +++ b/src/components/tab-bar/index.zh.md @@ -19,7 +19,7 @@ | 属性 | 说明 | 类型 | 默认值 | | --- | --- | --- | --- | | activeKey | 当前激活 `item` 的 `key` | `string \| null` | - | -| defaultActiveKey | 初始化选中 `item` 的 `key`,如果没有设置 `activeKey` | `string \| null` | 第一个 `Tab` 的 `key` | +| defaultActiveKey | 初始化选中 `item` 的 `key`,如果没有设置 `activeKey` | `string \| null` | 第一个 `TabBar.Item` 的 `key` | | onChange | 切换面板的回调 | `(key: string) => void` | - | | safeArea | 是否开启安全区适配 | `boolean` | `false` | From 42baf66d67584ce7ecae761e2d9b6214345d6a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=90=86=E5=A1=98=E7=9A=84=E5=B8=8C=E6=9C=9B?= <1587315093@qq.com> Date: Tue, 27 Jun 2023 11:18:58 +0800 Subject: [PATCH 21/23] doc: Simplified description of destroyOnClose (#6221) doc: simplified description of destroyOnClose --- src/components/action-sheet/index.en.md | 2 +- src/components/action-sheet/index.zh.md | 2 +- src/components/capsule-tabs/index.en.md | 2 +- src/components/capsule-tabs/index.zh.md | 2 +- src/components/cascader/index.en.md | 2 +- src/components/cascader/index.zh.md | 2 +- src/components/collapse/index.en.md | 2 +- src/components/collapse/index.zh.md | 2 +- src/components/dialog/index.en.md | 2 +- src/components/dialog/index.zh.md | 2 +- src/components/dropdown/index.en.md | 2 +- src/components/dropdown/index.zh.md | 2 +- src/components/jumbo-tabs/index.en.md | 2 +- src/components/jumbo-tabs/index.zh.md | 2 +- src/components/mask/index.en.md | 2 +- src/components/mask/index.zh.md | 2 +- src/components/modal/index.en.md | 2 +- src/components/modal/index.zh.md | 2 +- src/components/number-keyboard/index.en.md | 2 +- src/components/number-keyboard/index.zh.md | 2 +- src/components/picker/index.en.md | 4 ++-- src/components/picker/index.zh.md | 4 ++-- src/components/popup/index.en.md | 2 +- src/components/popup/index.zh.md | 2 +- src/components/tabs/index.en.md | 2 +- src/components/tabs/index.zh.md | 2 +- 26 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/components/action-sheet/index.en.md b/src/components/action-sheet/index.en.md index c040a5f09d..12babf2741 100644 --- a/src/components/action-sheet/index.en.md +++ b/src/components/action-sheet/index.en.md @@ -21,7 +21,7 @@ Triggered by user operation, it provides a set of two or more options related to | cancelText | The text of the cancel button , if it is null, the cancel button would not be displayed | `ReactNode` | - | | closeOnAction | Whether to close after clicking the option | `boolean` | `false` | | closeOnMaskClick | Whether to close after clicking the mask layer | `boolean` | `true` | -| destroyOnClose | Unmount content when not visible | `boolean` | `false` | +| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` | | forceRender | Render content forcely | `boolean` | `false` | | extra | The extra area at the top of the the action sheet | `ReactNode` | - | | getContainer | Get the specified mounted `HTML` node, the default is `body`, if `null` returned, it would be rendered to the current node | `HTMLElement \| () => HTMLElement \| null` | `document.body` | diff --git a/src/components/action-sheet/index.zh.md b/src/components/action-sheet/index.zh.md index cc1132dbf3..3efd1f2fda 100644 --- a/src/components/action-sheet/index.zh.md +++ b/src/components/action-sheet/index.zh.md @@ -21,7 +21,7 @@ | cancelText | 取消按钮文字,如果设置为空则不显示取消按钮 | `ReactNode` | - | | closeOnAction | 点击选项后是否关闭 | `boolean` | `false` | | closeOnMaskClick | 点击背景蒙层后是否关闭 | `boolean` | `true` | -| destroyOnClose | 不可见时卸载内容 | `boolean` | `false` | +| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` | | forceRender | 强制渲染内容 | `boolean` | `false` | | extra | 顶部的额外区域 | `ReactNode` | - | | getContainer | 指定挂载的 `HTML` 节点,默认为 `body`,如果为 `null` 的话,会渲染到当前节点 | `HTMLElement \| () => HTMLElement \| null` | `document.body` | diff --git a/src/components/capsule-tabs/index.en.md b/src/components/capsule-tabs/index.en.md index a84d277296..d5e3071794 100644 --- a/src/components/capsule-tabs/index.en.md +++ b/src/components/capsule-tabs/index.en.md @@ -26,7 +26,7 @@ Another style for tabs, used in lists or modules in presentational interfaces. | Name | Description | Type | Default | | --- | --- | --- | --- | -| destroyOnClose | Unmount content when not visible | `boolean` | `false` | +| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` | | disabled | Whether to disable the tab | `boolean` | `false` | | forceRender | Whether to render the `DOM` structure when hidden | `boolean` | `false` | | key | Corresponding to `activeKey` | `string` | - | diff --git a/src/components/capsule-tabs/index.zh.md b/src/components/capsule-tabs/index.zh.md index 54f9f66a15..3c7b9d4a8c 100644 --- a/src/components/capsule-tabs/index.zh.md +++ b/src/components/capsule-tabs/index.zh.md @@ -26,7 +26,7 @@ | 属性 | 说明 | 类型 | 默认值 | | -------------- | --------------------------- | ----------- | ------- | -| destroyOnClose | 不可见时卸载内容 | `boolean` | `false` | +| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` | | disabled | 是否禁用 | `boolean` | `false` | | forceRender | 被隐藏时是否渲染 `DOM` 结构 | `boolean` | `false` | | key | 对应 `activeKey` | `string` | - | diff --git a/src/components/cascader/index.en.md b/src/components/cascader/index.en.md index fab8b14e0b..8a5316c754 100644 --- a/src/components/cascader/index.en.md +++ b/src/components/cascader/index.en.md @@ -39,7 +39,7 @@ type CascaderValueExtend = { | children | Render function of the selected options | `(items: CascaderOption[], actions: CascaderActions) => ReactNode` | - | | confirmText | Text of the ok button | `ReactNode` | `'确定'` | | defaultValue | Default selected options | `CascaderValue[]` | `[]` | -| destroyOnClose | Unmount content when not visible | `boolean` | `true` | +| destroyOnClose | Destroy `dom` when not visible | `boolean` | `true` | | forceRender | Render content forcely | `boolean` | `false` | | onCancel | Triggered when cancelling | `() => void` | - | | onClose | Triggered when confirming or cancelling | `() => void` | - | diff --git a/src/components/cascader/index.zh.md b/src/components/cascader/index.zh.md index 294e77dc3f..7e8008080d 100644 --- a/src/components/cascader/index.zh.md +++ b/src/components/cascader/index.zh.md @@ -39,7 +39,7 @@ type CascaderValueExtend = { | children | 所选项的渲染函数 | `(items: CascaderOption[], actions: CascaderActions) => ReactNode` | - | | confirmText | 确定按钮的文字 | `ReactNode` | `'确定'` | | defaultValue | 默认选中项 | `CascaderValue[]` | `[]` | -| destroyOnClose | 不可见时卸载内容 | `boolean` | `true` | +| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `true` | | forceRender | 强制渲染内容 | `boolean` | `false` | | onCancel | 取消时触发 | `() => void` | - | | onClose | 确认和取消时都会触发关闭事件 | `() => void` | - | diff --git a/src/components/collapse/index.en.md b/src/components/collapse/index.en.md index bd8105441e..fb6dd655c7 100644 --- a/src/components/collapse/index.en.md +++ b/src/components/collapse/index.en.md @@ -32,7 +32,7 @@ A content area that can be collapsed/expanded. | Name | Description | Type | Default | | --- | --- | --- | --- | | arrow | Custom arrow | `React.ReactNode \| ((active: boolean) => React.ReactNode)` | - | -| destroyOnClose | Unmount content when not visible | `boolean` | `false` | +| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` | | disabled | Whether disabled or not | `boolean` | `false` | | forceRender | Whether to render the `DOM` structure when hidden | `boolean` | `false` | | key | The unique identifier | `string` | - | diff --git a/src/components/collapse/index.zh.md b/src/components/collapse/index.zh.md index 74671e77f1..44b5ef8779 100644 --- a/src/components/collapse/index.zh.md +++ b/src/components/collapse/index.zh.md @@ -32,7 +32,7 @@ | 属性 | 说明 | 类型 | 默认值 | | --- | --- | --- | --- | | arrow | 自定义箭头 | `ReactNode \| ((active: boolean) => React.ReactNode)` | - | -| destroyOnClose | 不可见时卸载内容 | `boolean` | `false` | +| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` | | disabled | 是否为禁用状态 | `boolean` | `false` | | forceRender | 被隐藏时是否渲染 `DOM` 结构 | `boolean` | `false` | | key | 唯一标识符 | `string` | - | diff --git a/src/components/dialog/index.en.md b/src/components/dialog/index.en.md index d534e76692..4a2375f800 100644 --- a/src/components/dialog/index.en.md +++ b/src/components/dialog/index.en.md @@ -28,7 +28,7 @@ When users need to process transactions, but do not want to jump to pages to int | closeOnAction | Whether to close after clicking the operation button | `boolean` | `false` | | closeOnMaskClick | Whether to support clicking the mask to close the dialog box | `boolean` | `false` | | content | The content of the Dialog | `React.ReactNode` | - | -| destroyOnClose | Unmount content when not visible | `boolean` | `false` | +| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` | | disableBodyScroll | Whether to disable `body` scrolling | `boolean` | `true` | | forceRender | Whether to render the `DOM` structure when hidden | `boolean` | `false` | | getContainer | The parent container of the custom dialog | `HTMLElement \| (() => HTMLElement) \| null` | `null` | diff --git a/src/components/dialog/index.zh.md b/src/components/dialog/index.zh.md index 641d7cea24..c22ecbd005 100644 --- a/src/components/dialog/index.zh.md +++ b/src/components/dialog/index.zh.md @@ -28,7 +28,7 @@ | closeOnAction | 点击操作按钮后后是否关闭 | `boolean` | `false` | | closeOnMaskClick | 是否支持点击遮罩关闭对话框 | `boolean` | `false` | | content | 对话框内容 | `React.ReactNode` | - | -| destroyOnClose | 不可见时卸载内容 | `boolean` | `false` | +| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` | | disableBodyScroll | 是否禁用 `body` 滚动 | `boolean` | `true` | | forceRender | 被隐藏时是否渲染 `DOM` 结构 | `boolean` | `false` | | getContainer | 自定义对话框的父容器 | `HTMLElement \| (() => HTMLElement) \| null` | `null` | diff --git a/src/components/dropdown/index.en.md b/src/components/dropdown/index.en.md index 0bcefd80eb..28f817a3db 100644 --- a/src/components/dropdown/index.en.md +++ b/src/components/dropdown/index.en.md @@ -37,7 +37,7 @@ It is suitable for filtering, sorting and changing the display range or order of | Name | Description | Type | Default | | --- | --- | --- | --- | | arrow | Custom arrow | `React.ReactNode` | - | -| destroyOnClose | Unmount content when not visible | `boolean` | `false` | +| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` | | forceRender | Whether to render the content even if it is not active | `boolean` | `false` | | highlight | Highlight | `boolean` | `false` | | key | The unique value | `string` | - | diff --git a/src/components/dropdown/index.zh.md b/src/components/dropdown/index.zh.md index e0bbe9608d..6558b1b360 100644 --- a/src/components/dropdown/index.zh.md +++ b/src/components/dropdown/index.zh.md @@ -37,7 +37,7 @@ | 属性 | 说明 | 类型 | 默认值 | | -------------- | --------------------------- | ----------------- | ------- | | arrow | 自定义 arrow | `React.ReactNode` | - | -| destroyOnClose | 不可见时卸载内容 | `boolean` | `false` | +| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` | | forceRender | 被隐藏时是否渲染 `DOM` 结构 | `boolean` | `false` | | highlight | 高亮 | `boolean` | `false` | | key | 唯一值 | `string` | - | diff --git a/src/components/jumbo-tabs/index.en.md b/src/components/jumbo-tabs/index.en.md index d4b1e09e62..f96feea0bd 100644 --- a/src/components/jumbo-tabs/index.en.md +++ b/src/components/jumbo-tabs/index.en.md @@ -25,7 +25,7 @@ Used in lists or modules in presentational interfaces when options require furth | Name | Description | Type | Default | | --- | --- | --- | --- | | description | The description text | `ReactNode` | - | -| destroyOnClose | Unmount content when not visible | `boolean` | `false` | +| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` | | disabled | Whether to disable the tab | `boolean` | `false` | | forceRender | Whether to render the `DOM` structure when hidden | `boolean` | `false` | | key | Corresponding to `activeKey` | `string` | - | diff --git a/src/components/jumbo-tabs/index.zh.md b/src/components/jumbo-tabs/index.zh.md index c3d329e3ea..9a762cadb2 100644 --- a/src/components/jumbo-tabs/index.zh.md +++ b/src/components/jumbo-tabs/index.zh.md @@ -25,7 +25,7 @@ | 属性 | 说明 | 类型 | 默认值 | | -------------- | --------------------------- | ----------- | ------- | | description | 选项卡描述 | `ReactNode` | - | -| destroyOnClose | 不可见时卸载内容 | `boolean` | `false` | +| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` | | disabled | 是否禁用 | `boolean` | `false` | | forceRender | 被隐藏时是否渲染 `DOM` 结构 | `boolean` | `false` | | key | 对应 `activeKey` | `string` | - | diff --git a/src/components/mask/index.en.md b/src/components/mask/index.en.md index bae4f6a1f4..97a8fcf1a3 100644 --- a/src/components/mask/index.en.md +++ b/src/components/mask/index.en.md @@ -19,7 +19,7 @@ Often used in the background layer of a modal window to make the visual focus st | afterClose | Triggered when completely closed | `() => void` | - | | afterShow | Triggered after fully displayed | `() => void` | - | | color | Color of the mask | `'black' \| 'white' \| string` | `'black'` | -| destroyOnClose | Uninstall content when invisible | `boolean` | `false` | +| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` | | disableBodyScroll | Whether to disable `body` scrolling | `boolean` | `true` | | forceRender | Render content forcely | `boolean` | `false` | | getContainer | To get the specified mounted `HTML` node, if `null` returned, it would be rendered to the current node | `HTMLElement \| () => HTMLElement \| null` | `null` | diff --git a/src/components/mask/index.zh.md b/src/components/mask/index.zh.md index 63b9223601..1ec0542b76 100644 --- a/src/components/mask/index.zh.md +++ b/src/components/mask/index.zh.md @@ -19,7 +19,7 @@ | afterClose | 完全关闭后触发 | `() => void` | - | | afterShow | 完全展示后触发 | `() => void` | - | | color | 背景蒙层的颜色 | `'black' \| 'white' \| string` | `'black'` | -| destroyOnClose | 不可见时卸载内容 | `boolean` | `false` | +| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` | | disableBodyScroll | 是否禁用 `body` 滚动 | `boolean` | `true` | | forceRender | 强制渲染内容 | `boolean` | `false` | | getContainer | 指定挂载的 `HTML` 节点,如果为 `null` 的话,会渲染到当前节点 | `HTMLElement \| () => HTMLElement \| null` | `null` | diff --git a/src/components/modal/index.en.md b/src/components/modal/index.en.md index ea442e86a4..47549a6e3c 100644 --- a/src/components/modal/index.en.md +++ b/src/components/modal/index.en.md @@ -28,7 +28,7 @@ When users need to process transactions, but do not want to jump to pages to int | closeOnAction | Whether to close after clicking the operation button | `boolean` | `false` | | closeOnMaskClick | Whether to support clicking the mask to close the modal box | `boolean` | `false` | | content | The content of the Modal | `React.ReactNode` | - | -| destroyOnClose | Unmount content when not visible | `boolean` | `false` | +| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` | | disableBodyScroll | Mask Whether to disable `body` scrolling | `boolean` | `true` | | forceRender | Whether to render the `DOM` structure when hidden | `boolean` | `false` | | getContainer | The parent container of the custom modal | `HTMLElement \| (() => HTMLElement) \| null` | `null` | diff --git a/src/components/modal/index.zh.md b/src/components/modal/index.zh.md index d20e63583b..75724b9e85 100644 --- a/src/components/modal/index.zh.md +++ b/src/components/modal/index.zh.md @@ -28,7 +28,7 @@ | closeOnAction | 点击操作按钮后后是否关闭 | `boolean` | `false` | | closeOnMaskClick | 是否支持点击遮罩关闭弹窗 | `boolean` | `false` | | content | 弹窗内容 | `React.ReactNode` | - | -| destroyOnClose | 不可见时卸载内容 | `boolean` | `false` | +| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` | | disableBodyScroll | 背景蒙层是否禁用 `body` 滚动 | `boolean` | `true` | | forceRender | 被隐藏时是否渲染 `DOM` 结构 | `boolean` | `false` | | getContainer | 自定义弹窗的父容器 | `HTMLElement \| (() => HTMLElement) \| null` | `null` | diff --git a/src/components/number-keyboard/index.en.md b/src/components/number-keyboard/index.en.md index f306d4394d..b778566a90 100644 --- a/src/components/number-keyboard/index.en.md +++ b/src/components/number-keyboard/index.en.md @@ -27,7 +27,7 @@ If possible, we recommend using the native keyboard provided by the system or cl | closeOnConfirm | Whether to automatically close when the ok button is clicked | `boolean` | `true` | | confirmText | The text of the confirm button, if `null` is set, it would be shown | `string \| null` | `null` | | customKey | Customized button | `string \| [string, string]` | - | -| destroyOnClose | Unmount content when not visible | `boolean` | `false` | +| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` | | forceRender | Render content forcely | `boolean` | `false` | | getContainer | To get the specified mounted HTML node, the default is `body`, if `null` returned, it would be rendered to the current node | `HTMLElement \| () => HTMLElement \| null` | `() => document.body` | | onClose | Triggered when it is clicked | `() => void` | - | diff --git a/src/components/number-keyboard/index.zh.md b/src/components/number-keyboard/index.zh.md index 37c3c43493..71464df5b9 100644 --- a/src/components/number-keyboard/index.zh.md +++ b/src/components/number-keyboard/index.zh.md @@ -27,7 +27,7 @@ | closeOnConfirm | 是否在点击确定按钮时自动关闭 | `boolean` | `true` | | confirmText | 完成按钮文案,`null` 不展示 | `string \| null` | `null` | | customKey | 自定义按钮 | `string \| [string, string]` | - | -| destroyOnClose | 不可见时卸载内容 | `boolean` | `false` | +| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` | | forceRender | 强制渲染内容 | `boolean` | `false` | | getContainer | 指定挂载的 HTML 节点,默认为 `body`,如果为 `null` 的话,会渲染到当前节点 | `HTMLElement \| () => HTMLElement \| null` | `() => document.body` | | onClose | 点击关闭时触发 | `() => void` | - | diff --git a/src/components/picker/index.en.md b/src/components/picker/index.en.md index 4c982fd9b6..6089776dda 100644 --- a/src/components/picker/index.en.md +++ b/src/components/picker/index.en.md @@ -43,7 +43,7 @@ type PickerValueExtend = { | columns | Options to configure each column | `PickerColumn[] \| ((value: PickerValue[]) => PickerColumn[])` | - | | confirmText | Text of the ok button | `ReactNode` | `'确定'` | | defaultValue | Default selected options | `PickerValue[]` | `[]` | -| destroyOnClose | Unmount content when not visible | `boolean` | `false` | +| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` | | forceRender | Render content forcely | `boolean` | `false` | | mouseWheel | Whether to allow interact with mouse wheel | `boolean` | `false` | | onCancel | Triggered when cancelling | `() => void` | - | @@ -154,7 +154,7 @@ type PickerDate = Date & { | --- | --- | --- | --- | --- | | children | The rendering function of the selected items | `(value: PickerDate, actions: PickerActions) => ReactNode` | - | | defaultValue | Default selected value | `PickerDate` | - | -| destroyOnClose | Unmount content when not visible | `boolean` | `false` | +| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` | | filter | Filter available time | `DatePickerFilter` | - | | forceRender | Render content forcely | `boolean` | `false` | | max | Max value | `PickerDate` | ten years later | diff --git a/src/components/picker/index.zh.md b/src/components/picker/index.zh.md index 948b1dd6cb..4b1b100d1b 100644 --- a/src/components/picker/index.zh.md +++ b/src/components/picker/index.zh.md @@ -43,7 +43,7 @@ type PickerValueExtend = { | columns | 配置每一列的选项 | `PickerColumn[] \| ((value: PickerValue[]) => PickerColumn[])` | - | | confirmText | 确定按钮的文字 | `ReactNode` | `'确定'` | | defaultValue | 默认选中项 | `PickerValue[]` | `[]` | -| destroyOnClose | 不可见时卸载内容 | `boolean` | `false` | +| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` | | forceRender | 强制渲染内容 | `boolean` | `false` | | mouseWheel | 是否允许通过鼠标滚轮进行选择 | `boolean` | `false` | | onCancel | 取消时触发 | `() => void` | - | @@ -156,7 +156,7 @@ type PickerDate = Date & { | --- | --- | --- | --- | --- | | children | 所选项的渲染函数 | `(value: PickerDate, actions: PickerActions) => ReactNode` | - | | defaultValue | 选中值 | `PickerDate` | - | -| destroyOnClose | 不可见时卸载内容 | `boolean` | `false` | +| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` | | filter | 过滤可供选择的时间 | `DatePickerFilter` | - | | forceRender | 强制渲染内容 | `boolean` | `false` | | max | 最大值 | `PickerDate` | 十年后 | diff --git a/src/components/popup/index.en.md b/src/components/popup/index.en.md index 30937dc00e..33bc6e6cdd 100644 --- a/src/components/popup/index.en.md +++ b/src/components/popup/index.en.md @@ -24,7 +24,7 @@ It is suitable for displaying pop-up windows, information prompts, selection inp | bodyStyle | Content section style | `React.CSSProperties` | - | | className | Container class name | `string` | - | | closeOnMaskClick | Whether to close after clicking the mask layer | `boolean` | `false` | -| destroyOnClose | Unmount content when not visible | `boolean` | `false` | +| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` | | forceRender | Render content forcely | `boolean` | `false` | | getContainer | To get the specified mounted `HTML` node, the default is `body`, if `null` returned, it would be rendered to the current node | `HTMLElement \| () => HTMLElement \| null` | `() => document.body` | | mask | Whether to display Mask | `boolean` | `true` | diff --git a/src/components/popup/index.zh.md b/src/components/popup/index.zh.md index ecff39dd3e..6c699b774c 100644 --- a/src/components/popup/index.zh.md +++ b/src/components/popup/index.zh.md @@ -24,7 +24,7 @@ | bodyStyle | 内容区域样式 | `React.CSSProperties` | - | | className | 容器类名 | `string` | - | | closeOnMaskClick | 点击背景蒙层后是否关闭 | `boolean` | `false` | -| destroyOnClose | 不可见时卸载内容 | `boolean` | `false` | +| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` | | forceRender | 强制渲染内容 | `boolean` | `false` | | getContainer | 指定挂载的 `HTML` 节点,默认为 `body`,如果为 `null` 的话,会渲染到当前节点 | `HTMLElement \| () => HTMLElement \| null` | `() => document.body` | | mask | 是否展示蒙层 | `boolean` | `true` | diff --git a/src/components/tabs/index.en.md b/src/components/tabs/index.en.md index 56cf56bb2a..d6e34ab092 100644 --- a/src/components/tabs/index.en.md +++ b/src/components/tabs/index.en.md @@ -45,7 +45,7 @@ The current content needs to be divided into groups of the same hierarchical str | Name | Description | Type | Default | | --- | --- | --- | --- | -| destroyOnClose | Unmount content when not visible | `boolean` | `false` | +| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` | | disabled | Whether to disable the tab | `boolean` | `false` | | forceRender | Whether to render the `DOM` structure when hidden | `boolean` | `false` | | key | Corresponding to `activeKey` | `string` | - | diff --git a/src/components/tabs/index.zh.md b/src/components/tabs/index.zh.md index f335a9c583..df3f840232 100644 --- a/src/components/tabs/index.zh.md +++ b/src/components/tabs/index.zh.md @@ -44,7 +44,7 @@ | 属性 | 说明 | 类型 | 默认值 | | -------------- | --------------------------- | ----------- | ------- | -| destroyOnClose | 不可见时卸载内容 | `boolean` | `false` | +| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` | | disabled | 是否禁用 | `boolean` | `false` | | forceRender | 被隐藏时是否渲染 `DOM` 结构 | `boolean` | `false` | | key | 对应 `activeKey` | `string` | - | From 48927a47b5274f494ef84d9111eb55efae35e74a Mon Sep 17 00:00:00 2001 From: miracles1919 <516571350@qq.com> Date: Thu, 29 Jun 2023 10:16:19 +0800 Subject: [PATCH 22/23] test: fix failed test (#6226) --- .../cascade-picker-view/tests/cascade-picker-view.test.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/cascade-picker-view/tests/cascade-picker-view.test.tsx b/src/components/cascade-picker-view/tests/cascade-picker-view.test.tsx index b66b8c5d91..09ba37d2bc 100644 --- a/src/components/cascade-picker-view/tests/cascade-picker-view.test.tsx +++ b/src/components/cascade-picker-view/tests/cascade-picker-view.test.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react' -import { render, testA11y, fireEvent, waitFor, actSleep } from 'testing' +import { render, testA11y, fireEvent, actSleep, act } from 'testing' import CascadePickerView from '..' import { options } from '../demos/options-data' @@ -7,7 +7,9 @@ const classPrefix = `adm-picker-view` describe('CascadePickerView', () => { test('a11y', async () => { - await waitFor(() => testA11y()) + await act(async () => { + await testA11y() + }) }) test('controlled mode', async () => { From 0f3409befdeccad9bced11e9387c52d6133a1d11 Mon Sep 17 00:00:00 2001 From: Wing <1587315093@qq.com> Date: Thu, 29 Jun 2023 17:19:57 +0800 Subject: [PATCH 23/23] doc: update Cascader&Cascaderview&Infinitescroll docs (#6225) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * doc: infinitescroll组件语义修改&cascaderview骨架屏demo案例修复 * doc: 补充casvader的loading属性 * doc: update docs --- src/components/cascader-view/demos/demo1.tsx | 26 +++----------------- src/components/cascader/cascader.tsx | 1 + src/components/cascader/index.en.md | 1 + src/components/cascader/index.zh.md | 1 + src/components/infinite-scroll/index.en.md | 6 +++-- src/components/infinite-scroll/index.zh.md | 6 +++-- 6 files changed, 14 insertions(+), 27 deletions(-) diff --git a/src/components/cascader-view/demos/demo1.tsx b/src/components/cascader-view/demos/demo1.tsx index c00d7494e2..8efd9f163f 100644 --- a/src/components/cascader-view/demos/demo1.tsx +++ b/src/components/cascader-view/demos/demo1.tsx @@ -1,30 +1,11 @@ import React, { useState } from 'react' -import { CascaderView, Button } from 'antd-mobile' +import { CascaderView } from 'antd-mobile' import { DemoBlock } from 'demos' import { options, sameValueOptions } from '../../cascader/demos/data' -const list1 = [ - { - label: '西湖区', - value: '西湖区', - }, - { - label: '上城区', - value: '上城区', - }, - { - label: '余杭区', - value: '余杭区', - disabled: true, - }, -] - export default () => { const [value, setValue] = useState([]) - const [list, setList] = useState([]) - - console.log(list, 'list') return ( <> @@ -55,9 +36,8 @@ export default () => { }} /> - - - + + ) diff --git a/src/components/cascader/cascader.tsx b/src/components/cascader/cascader.tsx index 65e4bed8d3..3d4a8a0e49 100644 --- a/src/components/cascader/cascader.tsx +++ b/src/components/cascader/cascader.tsx @@ -40,6 +40,7 @@ export type CascaderProps = { title?: ReactNode confirmText?: ReactNode cancelText?: ReactNode + loading?: boolean children?: ( items: (CascaderOption | null)[], actions: CascaderActions diff --git a/src/components/cascader/index.en.md b/src/components/cascader/index.en.md index 8a5316c754..78100ec70f 100644 --- a/src/components/cascader/index.en.md +++ b/src/components/cascader/index.en.md @@ -51,6 +51,7 @@ type CascaderValueExtend = { | title | Title | `ReactNode` | - | | value | Selected options | `CascaderValue[]` | - | | visible | Whether to show or hide the Picker | `boolean` | `false` | +| loading | Open the skeleton screen | `boolean` | `false` | Please pay attention to the `children` property of `CascaderOption`. If the `children` of an `option` is `[]`, then when the user selects this `option`, the Cascader component will automatically jump to the next level, even if There are currently no options at this level (because Cascader has no way to determine whether this empty array will become an array with content in subsequent updates). Therefore, please make sure that the `children` property of the last level option (aka "leaf node") does not exist or has the value `undefined`, so that the Cascader component can correctly recognize it. diff --git a/src/components/cascader/index.zh.md b/src/components/cascader/index.zh.md index 7e8008080d..9310cb7bd1 100644 --- a/src/components/cascader/index.zh.md +++ b/src/components/cascader/index.zh.md @@ -51,6 +51,7 @@ type CascaderValueExtend = { | title | 标题 | `ReactNode` | - | | value | 选中项 | `CascaderValue[]` | - | | visible | 是否显示级联选择 | `boolean` | `false` | +| loading | 开启骨架屏 | `boolean` | `false` | 请留意 `CascaderOption` 的 `children` 属性,如果某个 `option` 的 `children` 为 `[]`,那当用户选择了这个 `option` 时,Cascader 组件会自动跳转到下一级,即便这一级当前是没有任何选项的(因为 Cascader 没有办法判断,在后续的更新中,这个空数组会不会变为一个有内容的数组)。因此,请确保最末一级的 option(也就是"叶子节点")的 `children` 属性不存在或者值为 `undefined`,这样 Cascader 组件才能将其正确地识别。 diff --git a/src/components/infinite-scroll/index.en.md b/src/components/infinite-scroll/index.en.md index bca49131af..4dfe7cee0b 100644 --- a/src/components/infinite-scroll/index.en.md +++ b/src/components/infinite-scroll/index.en.md @@ -45,7 +45,7 @@ function loadMore() { // ok ### Customized Content -If necessary, `` allows custom display content, this content can contain any element, including svg and elements with css animation. +If necessary, `InfiniteScroll` allows custom display content, this content can contain any element, including svg and elements with css animation. @@ -93,7 +93,9 @@ But in some scenarios (for example, when used with the `Tabs` component), you ma ``` -Problem description: The `Tabs` component displays the content of the first `Tab` item by default, so the content of the second `Tab` item `InfiniteScroll` is not visible. But the second `Tab` has a `forceRender` property added, so its content is rendered even if it is not visible. When the `InfiniteScroll` component is rendered this time, since the component is not visible, the `loadMore` function will not be called, which is normal and as expected. _However, when we switch to the second `Tab` to display the `InfiniteScroll` component, we find that the `InfiniteScroll` component does not call the `loadMore` function, which is different from what we expected. We hope that the `loadMore` function will be called at this time_. +Problem description: The `Tabs` component displays the content of the first `Tab` item by default, so the content of the second `Tab` item `InfiniteScroll` is not visible. But the second `Tab` has a `forceRender` property added, so its content is rendered even if it is not visible. When the `InfiniteScroll` component is rendered this time, since the component is not visible, the `loadMore` function will not be called, which is normal and as expected. + +_However, when we switch to the second `Tab` to display the `InfiniteScroll` component, we find that the `InfiniteScroll` component does not call the `loadMore` function, which is different from what we expected. We hope that the `loadMore` function will be called at this time_. Reason: When you click to switch the `Tab` item of the `Tabs` component, the highlight state of the `Tabs` component will be modified. At this time, the `Tabs` component will be re-rendered. However, it should be noted that **only the content of the `Tabs` component itself will be re-rendered, and the `InfiniteScroll` component is outside the `Tabs` component, not the `Tabs` component's own content**. So, when switching `Tab`, the `InfiniteScroll` component does not re-render, and it does not trigger its checking mechanism again. diff --git a/src/components/infinite-scroll/index.zh.md b/src/components/infinite-scroll/index.zh.md index 826240a932..47bf6d02e7 100644 --- a/src/components/infinite-scroll/index.zh.md +++ b/src/components/infinite-scroll/index.zh.md @@ -45,7 +45,7 @@ function loadMore() { // 正确 ### 自定义 Content -如果需要的话,`` 允许自定义展示内容,这个内容可以包含任何元素,包括 svg 和带有 css 动画的元素。 +如果需要的话,`InfiniteScroll` 允许自定义展示内容,这个内容可以包含任何元素,包括 svg 和带有 css 动画的元素。 @@ -93,7 +93,9 @@ InfiniteScroll 本身已经包含了防止并发的重复请求的逻辑,所 ``` -问题描述:`Tabs` 组件默认展示第一个 `Tab` 项的内容,所以,第二个 `Tab` 项的内容 `InfiniteScroll` 是不可见的。但第二个 `Tab` 添加了 `forceRender` 属性,所以即使不可见,其内容也会渲染。本次渲染 `InfiniteScroll`组件时,由于该组件不可见,所以,不会调用 `loadMore` 函数,这是正常的,跟我们的预期相同。_但是,当我们切换到第二个 `Tab` 展示 `InfiniteScroll` 组件时,发现 `InfiniteScroll` 组件并没有调用 `loadMore` 函数,这一点跟我们预期不同,我们希望此时 `loadMore` 函数被调用_。 +问题描述:`Tabs` 组件默认展示第一个 `Tab` 项的内容,所以,第二个 `Tab` 项的内容 `InfiniteScroll` 是不可见的。但第二个 `Tab` 添加了 `forceRender` 属性,所以即使不可见,其内容也会渲染。本次渲染 `InfiniteScroll`组件时,由于该组件不可见,所以,不会调用 `loadMore` 函数,这是正常的,跟我们的预期相同。 + +_但是,当我们切换到第二个 `Tab` 展示 `InfiniteScroll` 组件时,发现 `InfiniteScroll` 组件并没有调用 `loadMore` 函数,这一点跟我们预期不同,我们希望此时 `loadMore` 函数被调用_。 原因说明:点击切换 `Tabs` 组件的 `Tab` 项时,会修改 `Tabs` 组件的高亮状态,此时,`Tabs` 组件会重新渲染。但是,要注意的是**只有在 `Tabs` 组件自身的内容才会被重新渲染,而 `InfiniteScroll` 组件是在 `Tabs` 组件外部的,并非 `Tabs` 组件自身内容**。所以,切换 `Tab` 时,`InfiniteScroll` 组件并不会重新渲染,也就没有再次触发它的检查机制。