From 8bc0c29a59e75d594733311ef60ea5b2eb57cb70 Mon Sep 17 00:00:00 2001 From: mackwang Date: Mon, 11 May 2026 21:30:45 +0800 Subject: [PATCH 1/5] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=20customDimension?= =?UTF-8?q?s=20=E7=B1=BB=E5=9E=8B=E5=AE=9A=E4=B9=89=EF=BC=8C=E5=8E=BB?= =?UTF-8?q?=E9=99=A4=E6=97=A0=E6=84=8F=E4=B9=89=E6=B3=9B=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- docs-vitepress/guide/rn/application-api.md | 37 +++++++++++++ packages/core/@types/index.d.ts | 18 +++++-- .../builtInMixins/styleHelperMixin.ios.js | 53 +++++++++++++------ 3 files changed, 88 insertions(+), 20 deletions(-) diff --git a/docs-vitepress/guide/rn/application-api.md b/docs-vitepress/guide/rn/application-api.md index ba225bbfa8..3429d79d1e 100644 --- a/docs-vitepress/guide/rn/application-api.md +++ b/docs-vitepress/guide/rn/application-api.md @@ -463,6 +463,43 @@ createComponent({ 例如: 在折叠屏中我们期望只在其中一半屏上展示,可在 customDimensions 中判断当前是否为折叠屏展开状态,如果是则将 ScreenWidth 设置为原来的一半。 +#### mpx.config.rnConfig.notifyDimensionsChange + +```ts +(dimensions?: { window: ScaledSize; screen: ScaledSize }) => void +``` + +主动通知框架 dimensions 发生变化,触发 rpx、vw、vh、媒体查询、onResize 等的重新计算。 + +框架默认已监听 `Dimensions.addEventListener('change', ...)` 自动处理尺寸变化。在某些容器环境下(如折叠屏、分屏)系统事件无法正常触发时,可手动调用此方法驱动更新。不传参时默认使用当前全局 dimensions。 + +**传入 dimensions(系统事件无法触发时):** + +```javascript +// 示例:折叠屏展开/折叠时手动通知框架 +import { Dimensions } from 'react-native' + +foldableScreen.on('change', () => { + mpx.config.rnConfig.notifyDimensionsChange({ + window: Dimensions.get('window'), + screen: Dimensions.get('screen') + }) +}) +``` + +**不传参(`customDimensions` 逻辑变更后重新应用):** + +`customDimensions` 是在 dimensions 变化时被调用的转换函数,如果运行时动态修改了 `customDimensions` 的逻辑,需要用无参调用让框架以当前屏幕尺寸重新执行一次 `customDimensions`,使新逻辑立即生效。 + +```javascript +// 示例:切换折叠屏展示模式后,重新应用 customDimensions +mpx.config.rnConfig.customDimensions = ({ window, screen }) => { + // 更新后的转换逻辑 + return isFolded ? { window, screen } : { window, screen: { ...screen, width: screen.width / 2 } } +} +// 不传参,用当前屏幕尺寸重新触发 customDimensions +mpx.config.rnConfig.notifyDimensionsChange() +``` ### 前后台切换 {#app-state-change} diff --git a/packages/core/@types/index.d.ts b/packages/core/@types/index.d.ts index 41c6840928..f31a5a7c09 100644 --- a/packages/core/@types/index.d.ts +++ b/packages/core/@types/index.d.ts @@ -376,9 +376,21 @@ export interface RnConfig { * @param dimensions 包含 window 和 screen 的尺寸信息 * @returns 返回修改后的尺寸对象,或 void 表示不修改 */ - customDimensions?: ( - dimensions: T - ) => T | void + customDimensions?: ( + dimensions: { window: ScaledSize; screen: ScaledSize } + ) => { window: ScaledSize; screen: ScaledSize } | void + + /** + * 主动通知框架 dimensions 发生变化,触发 rpx、vw、vh、媒体查询、onResize 等的重新计算。 + * + * 框架默认已监听 `Dimensions.addEventListener('change', ...)` 自动处理, + * 在某些容器环境下(如折叠屏、分屏)系统事件无法正常触发时,可手动调用此方法驱动更新。 + * + * 不传参时默认使用当前全局 dimensions。 + * + * @param dimensions 包含 window 和 screen 的尺寸信息,不传则使用当前全局 dimensions + */ + notifyDimensionsChange?: (dimensions?: { window: ScaledSize; screen: ScaledSize }) => void /** * 加载并执行异步分包的方法。 diff --git a/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js b/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js index 0628aaf89f..de946f4f6e 100644 --- a/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js +++ b/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js @@ -4,8 +4,8 @@ import { reactive } from '../../observer/reactive' import Mpx from '../../index' global.__mpxAppDimensionsInfo = { - window: Dimensions.get('window'), - screen: Dimensions.get('screen') + window: Object.assign({}, Dimensions.get('window')), + screen: Object.assign({}, Dimensions.get('screen')) } global.__mpxSizeCount = 0 global.__mpxPageSizeCountMap = reactive({}) @@ -18,30 +18,40 @@ global.__GCC = function (className, classMap, classMapValueCache) { return classMapValueCache.get(className) } -let dimensionsInfoInitialized = false -function useDimensionsInfo (dimensions) { - dimensionsInfoInitialized = true +function getPageSize (screen = global.__mpxAppDimensionsInfo.screen) { + return screen.width + 'x' + screen.height +} + +// 将 dimensions 写入全局(支持 customDimensions 自定义),返回最终生效的 dimensions +function applyDimensionsInfo (dimensions) { if (typeof Mpx.config.rnConfig?.customDimensions === 'function') { dimensions = Mpx.config.rnConfig.customDimensions(dimensions) || dimensions } global.__mpxAppDimensionsInfo.window = dimensions.window global.__mpxAppDimensionsInfo.screen = dimensions.screen + return dimensions } -function getPageSize (window = global.__mpxAppDimensionsInfo.screen) { - return window.width + 'x' + window.height -} - -Dimensions.addEventListener('change', ({ window, screen }) => { - const oldScreen = getPageSize(global.__mpxAppDimensionsInfo.screen) - useDimensionsInfo({ window, screen }) +function onDimensionsChange (dimensions) { + const oldScreen = getPageSize() + /** + * 鸿蒙上在屏幕尺寸不变时,调用 Dimensions.get 获取到的返回值都是同一个对象, + * 为防止外部修改dimensions导致影响其他位置调用Dimensions.get的返回,所以clone一份进行后续处理 + */ + if (!dimensions) { + dimensions = { + window: Dimensions.get('window'), + screen: Dimensions.get('screen') + } + } + applyDimensionsInfo({ window: Object.assign({}, dimensions.window), screen: Object.assign({}, dimensions.screen) }) - // 对比 screen 高宽是否存在变化 - if (getPageSize(screen) === oldScreen) return + // screen 高宽未变化时不触发 resize 副作用 + if (getPageSize() === oldScreen) return global.__classCaches?.forEach(cache => cache?.clear()) - // 更新全局和栈顶页面的标记,其他后台页面的标记在show之后更新 + // 更新全局和栈顶页面的标记,其他后台页面的标记在 show 之后更新 global.__mpxSizeCount++ const navigation = getFocusedNavigation() @@ -52,7 +62,9 @@ Dimensions.addEventListener('change', ({ window, screen }) => { global.__mpxPageStatusMap[navigation.pageId] = `resize${global.__mpxSizeCount}` } } -}) +} + +Dimensions.addEventListener('change', onDimensionsChange) // TODO: 1 目前测试鸿蒙下折叠屏screen固定为展开状态下屏幕尺寸,仅window会变化,且window包含状态栏高度 // TODO: 2 存在部分安卓折叠屏机型在折叠/展开切换时,Dimensions监听到的width/height尺寸错误,并触发多次问题 @@ -79,8 +91,15 @@ const unit = { const empty = {} +let dimensionsApplied = false function formatValue (value, unitType) { - if (!dimensionsInfoInitialized) useDimensionsInfo(global.__mpxAppDimensionsInfo) + // 懒初始化:首次调用时将初始 dimensions 写入全局(触发 customDimensions 处理) + if (!dimensionsApplied) { + dimensionsApplied = true + applyDimensionsInfo(global.__mpxAppDimensionsInfo) + // 默认实现:不传参时通过 Dimensions 实时获取当前屏幕尺寸(拷贝一份防止原对象被外部修改) + Mpx.config.rnConfig.notifyDimensionsChange = onDimensionsChange + } if (unitType === 'hairlineWidth') { return StyleSheet.hairlineWidth } From 2cbd765ffaa01da1300fff9ed850a18835008955 Mon Sep 17 00:00:00 2001 From: mackwang Date: Mon, 11 May 2026 21:56:12 +0800 Subject: [PATCH 2/5] =?UTF-8?q?fix:=20=E5=B0=86=20notifyDimensionsChange?= =?UTF-8?q?=20=E6=94=B9=E4=B8=BA=E5=85=A8=E5=B1=80=E6=96=B9=E6=B3=95?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=AD=A3=E7=B1=BB=E5=9E=8B=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- packages/core/@types/global.d.ts | 12 ++++++++++++ packages/core/@types/index.d.ts | 12 ------------ .../platform/builtInMixins/styleHelperMixin.ios.js | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/core/@types/global.d.ts b/packages/core/@types/global.d.ts index 51dbff4263..a71465eb78 100644 --- a/packages/core/@types/global.d.ts +++ b/packages/core/@types/global.d.ts @@ -14,3 +14,15 @@ declare module '*?resolve' { declare let setAppShow: () => void declare let setAppHide: () => void + +/** + * 主动通知框架 dimensions 发生变化,触发 rpx、vw、vh、媒体查询、onResize 等的重新计算。 + * + * 框架默认已监听 `Dimensions.addEventListener('change', ...)` 自动处理, + * 在某些容器环境下(如折叠屏、分屏)系统事件无法正常触发时,可手动调用此方法驱动更新。 + * + * 不传参时默认使用当前全局 dimensions。 + * + * @param dimensions 包含 window 和 screen 的尺寸信息,不传则使用当前全局 dimensions + */ +declare let notifyDimensionsChange: (dimensions?: { window: import('react-native').ScaledSize; screen: import('react-native').ScaledSize }) => void diff --git a/packages/core/@types/index.d.ts b/packages/core/@types/index.d.ts index f31a5a7c09..237a7d1b22 100644 --- a/packages/core/@types/index.d.ts +++ b/packages/core/@types/index.d.ts @@ -380,18 +380,6 @@ export interface RnConfig { dimensions: { window: ScaledSize; screen: ScaledSize } ) => { window: ScaledSize; screen: ScaledSize } | void - /** - * 主动通知框架 dimensions 发生变化,触发 rpx、vw、vh、媒体查询、onResize 等的重新计算。 - * - * 框架默认已监听 `Dimensions.addEventListener('change', ...)` 自动处理, - * 在某些容器环境下(如折叠屏、分屏)系统事件无法正常触发时,可手动调用此方法驱动更新。 - * - * 不传参时默认使用当前全局 dimensions。 - * - * @param dimensions 包含 window 和 screen 的尺寸信息,不传则使用当前全局 dimensions - */ - notifyDimensionsChange?: (dimensions?: { window: ScaledSize; screen: ScaledSize }) => void - /** * 加载并执行异步分包的方法。 * diff --git a/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js b/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js index de946f4f6e..bf7e1f221e 100644 --- a/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js +++ b/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js @@ -63,6 +63,8 @@ function onDimensionsChange (dimensions) { } } } +// 默认实现:不传参时通过 Dimensions 实时获取当前屏幕尺寸(拷贝一份防止原对象被外部修改) +global.notifyDimensionsChange = onDimensionsChange Dimensions.addEventListener('change', onDimensionsChange) @@ -97,8 +99,6 @@ function formatValue (value, unitType) { if (!dimensionsApplied) { dimensionsApplied = true applyDimensionsInfo(global.__mpxAppDimensionsInfo) - // 默认实现:不传参时通过 Dimensions 实时获取当前屏幕尺寸(拷贝一份防止原对象被外部修改) - Mpx.config.rnConfig.notifyDimensionsChange = onDimensionsChange } if (unitType === 'hairlineWidth') { return StyleSheet.hairlineWidth From d02e51b34d3faa194557805340b338c1465e92f4 Mon Sep 17 00:00:00 2001 From: mackwang Date: Mon, 11 May 2026 22:02:07 +0800 Subject: [PATCH 3/5] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=20notifyDimensio?= =?UTF-8?q?nsChange=20=E6=96=87=E6=A1=A3=EF=BC=8C=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=96=B9=E6=B3=95=E8=B0=83=E7=94=A8=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- docs-vitepress/guide/rn/application-api.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs-vitepress/guide/rn/application-api.md b/docs-vitepress/guide/rn/application-api.md index 3429d79d1e..12154da107 100644 --- a/docs-vitepress/guide/rn/application-api.md +++ b/docs-vitepress/guide/rn/application-api.md @@ -463,7 +463,7 @@ createComponent({ 例如: 在折叠屏中我们期望只在其中一半屏上展示,可在 customDimensions 中判断当前是否为折叠屏展开状态,如果是则将 ScreenWidth 设置为原来的一半。 -#### mpx.config.rnConfig.notifyDimensionsChange +#### notifyDimensionsChange ```ts (dimensions?: { window: ScaledSize; screen: ScaledSize }) => void @@ -480,7 +480,7 @@ createComponent({ import { Dimensions } from 'react-native' foldableScreen.on('change', () => { - mpx.config.rnConfig.notifyDimensionsChange({ + notifyDimensionsChange({ window: Dimensions.get('window'), screen: Dimensions.get('screen') }) @@ -498,7 +498,7 @@ mpx.config.rnConfig.customDimensions = ({ window, screen }) => { return isFolded ? { window, screen } : { window, screen: { ...screen, width: screen.width / 2 } } } // 不传参,用当前屏幕尺寸重新触发 customDimensions -mpx.config.rnConfig.notifyDimensionsChange() +notifyDimensionsChange() ``` ### 前后台切换 {#app-state-change} From 904d176b1765cc986643f813d50047770a1fd5fd Mon Sep 17 00:00:00 2001 From: mackwang Date: Mon, 11 May 2026 22:04:24 +0800 Subject: [PATCH 4/5] =?UTF-8?q?docs:=20=E5=B0=86=20notifyDimensionsChange?= =?UTF-8?q?=20=E6=96=87=E6=A1=A3=E7=A7=BB=E8=87=B3=E5=85=A8=E5=B1=80=20API?= =?UTF-8?q?=20=E7=AB=A0=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- .../mpx2rn/references/rn-script-reference.md | 2 + docs-vitepress/guide/rn/application-api.md | 38 ------------------- 2 files changed, 2 insertions(+), 38 deletions(-) diff --git a/.agents/skills/mpx2rn/references/rn-script-reference.md b/.agents/skills/mpx2rn/references/rn-script-reference.md index ee8dba4173..09d37e9b9b 100644 --- a/.agents/skills/mpx2rn/references/rn-script-reference.md +++ b/.agents/skills/mpx2rn/references/rn-script-reference.md @@ -587,11 +587,13 @@ setAppHide() | `getCurrentPages()` | 返回当前导航栈中已映射的页面实例列表(顺序与路由 state 相关)。 | | `setAppShow()` | 手动触发应用「进入前台」逻辑,驱动已注册的 `onShow`。 | | `setAppHide()` | 手动触发应用「进入后台」逻辑,驱动已注册的 `onHide`。 | +| `notifyDimensionsChange(dimensions?)` | 主动通知框架 dimensions 发生变化,触发 rpx、vw、vh、媒体查询、onResize 等的重新计算。在某些容器环境下(如折叠屏、分屏)系统 `Dimensions` 事件无法正常触发时使用。不传参时默认使用当前全局 dimensions 并重新执行 `customDimensions`。 | #### 注意事项 - 勿在 App 构造函数执行完成前依赖 `getApp()` 内业务字段已赋值完毕;与路由相关的初始化宜放在 `onLaunch` / `onShow`。 - `getCurrentPages()` 依赖 React Navigation 焦点与 `__mpxPagesMap`,与原生小程序栈细节不完全相同。 +- `notifyDimensionsChange` 由框架在首次样式计算时自动注入,可在业务代码任意位置调用。 --- diff --git a/docs-vitepress/guide/rn/application-api.md b/docs-vitepress/guide/rn/application-api.md index 12154da107..fd7185eb1d 100644 --- a/docs-vitepress/guide/rn/application-api.md +++ b/docs-vitepress/guide/rn/application-api.md @@ -463,44 +463,6 @@ createComponent({ 例如: 在折叠屏中我们期望只在其中一半屏上展示,可在 customDimensions 中判断当前是否为折叠屏展开状态,如果是则将 ScreenWidth 设置为原来的一半。 -#### notifyDimensionsChange - -```ts -(dimensions?: { window: ScaledSize; screen: ScaledSize }) => void -``` - -主动通知框架 dimensions 发生变化,触发 rpx、vw、vh、媒体查询、onResize 等的重新计算。 - -框架默认已监听 `Dimensions.addEventListener('change', ...)` 自动处理尺寸变化。在某些容器环境下(如折叠屏、分屏)系统事件无法正常触发时,可手动调用此方法驱动更新。不传参时默认使用当前全局 dimensions。 - -**传入 dimensions(系统事件无法触发时):** - -```javascript -// 示例:折叠屏展开/折叠时手动通知框架 -import { Dimensions } from 'react-native' - -foldableScreen.on('change', () => { - notifyDimensionsChange({ - window: Dimensions.get('window'), - screen: Dimensions.get('screen') - }) -}) -``` - -**不传参(`customDimensions` 逻辑变更后重新应用):** - -`customDimensions` 是在 dimensions 变化时被调用的转换函数,如果运行时动态修改了 `customDimensions` 的逻辑,需要用无参调用让框架以当前屏幕尺寸重新执行一次 `customDimensions`,使新逻辑立即生效。 - -```javascript -// 示例:切换折叠屏展示模式后,重新应用 customDimensions -mpx.config.rnConfig.customDimensions = ({ window, screen }) => { - // 更新后的转换逻辑 - return isFolded ? { window, screen } : { window, screen: { ...screen, width: screen.width / 2 } } -} -// 不传参,用当前屏幕尺寸重新触发 customDimensions -notifyDimensionsChange() -``` - ### 前后台切换 {#app-state-change} #### mpx.config.rnConfig.disableAppStateListener From dc37d71fda0a8cc562b7e5c91d7082b07ce3b645 Mon Sep 17 00:00:00 2001 From: mackwang Date: Mon, 11 May 2026 22:08:47 +0800 Subject: [PATCH 5/5] =?UTF-8?q?docs:=20notifyDimensionsChange=20=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../skills/mpx2rn/references/rn-script-reference.md | 4 ++-- packages/core/@types/global.d.ts | 10 ---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/.agents/skills/mpx2rn/references/rn-script-reference.md b/.agents/skills/mpx2rn/references/rn-script-reference.md index 09d37e9b9b..2c10faa553 100644 --- a/.agents/skills/mpx2rn/references/rn-script-reference.md +++ b/.agents/skills/mpx2rn/references/rn-script-reference.md @@ -587,13 +587,13 @@ setAppHide() | `getCurrentPages()` | 返回当前导航栈中已映射的页面实例列表(顺序与路由 state 相关)。 | | `setAppShow()` | 手动触发应用「进入前台」逻辑,驱动已注册的 `onShow`。 | | `setAppHide()` | 手动触发应用「进入后台」逻辑,驱动已注册的 `onHide`。 | -| `notifyDimensionsChange(dimensions?)` | 主动通知框架 dimensions 发生变化,触发 rpx、vw、vh、媒体查询、onResize 等的重新计算。在某些容器环境下(如折叠屏、分屏)系统 `Dimensions` 事件无法正常触发时使用。不传参时默认使用当前全局 dimensions 并重新执行 `customDimensions`。 | +| `notifyDimensionsChange(dimensions?)` | 主动通知框架 dimensions 发生变化,触发 rpx、vw、vh、媒体查询、onResize 等的重新计算。不传参时默认使用当前屏幕 dimensions 并重新执行 `customDimensions`。 | #### 注意事项 - 勿在 App 构造函数执行完成前依赖 `getApp()` 内业务字段已赋值完毕;与路由相关的初始化宜放在 `onLaunch` / `onShow`。 - `getCurrentPages()` 依赖 React Navigation 焦点与 `__mpxPagesMap`,与原生小程序栈细节不完全相同。 -- `notifyDimensionsChange` 由框架在首次样式计算时自动注入,可在业务代码任意位置调用。 +- `notifyDimensionsChange` 由框架在首次样式计算时自动注入,需在开始渲染后才可调用。 --- diff --git a/packages/core/@types/global.d.ts b/packages/core/@types/global.d.ts index a71465eb78..7a3297f9db 100644 --- a/packages/core/@types/global.d.ts +++ b/packages/core/@types/global.d.ts @@ -15,14 +15,4 @@ declare module '*?resolve' { declare let setAppShow: () => void declare let setAppHide: () => void -/** - * 主动通知框架 dimensions 发生变化,触发 rpx、vw、vh、媒体查询、onResize 等的重新计算。 - * - * 框架默认已监听 `Dimensions.addEventListener('change', ...)` 自动处理, - * 在某些容器环境下(如折叠屏、分屏)系统事件无法正常触发时,可手动调用此方法驱动更新。 - * - * 不传参时默认使用当前全局 dimensions。 - * - * @param dimensions 包含 window 和 screen 的尺寸信息,不传则使用当前全局 dimensions - */ declare let notifyDimensionsChange: (dimensions?: { window: import('react-native').ScaledSize; screen: import('react-native').ScaledSize }) => void