Skip to content
2 changes: 2 additions & 0 deletions .agents/skills/mpx2rn/references/rn-script-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -759,11 +759,13 @@ setAppHide()
| `getCurrentPages()` | 返回当前导航栈中已映射的页面实例列表(顺序与路由 state 相关)。 |
| `setAppShow()` | 手动触发应用「进入前台」逻辑,驱动已注册的 `onShow`。 |
| `setAppHide()` | 手动触发应用「进入后台」逻辑,驱动已注册的 `onHide`。 |
| `notifyDimensionsChange(dimensions?)` | 主动通知框架 dimensions 发生变化,触发 rpx、vw、vh、媒体查询、onResize 等的重新计算。不传参时默认使用当前屏幕 dimensions 并重新执行 `customDimensions`。 |

#### 注意事项

- 勿在 App 构造函数执行完成前依赖 `getApp()` 内业务字段已赋值完毕;与路由相关的初始化宜放在 `onLaunch` / `onShow`。
- `getCurrentPages()` 依赖 React Navigation 焦点与 `__mpxPagesMap`,与原生小程序栈细节不完全相同。
- `notifyDimensionsChange` 由框架在首次样式计算时自动注入,需在开始渲染后才可调用。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] 修正 API 注入时机,并补齐用户文档

这里写的是“首次样式计算时自动注入”,但实现是在 styleHelperMixin.ios.js 模块加载时直接执行 global.notifyDimensionsChange = onDimensionsChange,与首次 formatValue() 调用无关,建议按实际实现修正说明。

此外,docs-vitepress/guide/rn/application-api.md 在本 PR 中仅删除空行,没有新增 notifyDimensionsChange 的使用说明,尚未满足仓库对新增公开 API 的文档同步要求。建议在折叠屏适配章节补充参数、无参时从 Dimensions.get 读取原始尺寸并重新执行 customDimensions 的行为,以及调用示例。


---

Expand Down
1 change: 0 additions & 1 deletion docs-vitepress/guide/rn/application-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,6 @@ mpx.config.rnConfig.disablePageTransition = true

例如: 在折叠屏中我们期望只在其中一半屏上展示,可在 customDimensions 中判断当前是否为折叠屏展开状态,如果是则将 ScreenWidth 设置为原来的一半。


### 前后台切换 {#app-state-change}

#### mpx.config.rnConfig.disableAppStateListener
Expand Down
2 changes: 2 additions & 0 deletions packages/core/@types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ declare module '*?resolve' {

declare let setAppShow: () => void
declare let setAppHide: () => void

declare let notifyDimensionsChange: (dimensions?: { window: import('react-native').ScaledSize; screen: import('react-native').ScaledSize }) => void
6 changes: 3 additions & 3 deletions packages/core/@types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,9 +481,9 @@ export interface RnConfig {
* @param dimensions 包含 window 和 screen 的尺寸信息
* @returns 返回修改后的尺寸对象,或 void 表示不修改
*/
customDimensions?: <T extends { window: ScaledSize; screen: ScaledSize }>(
dimensions: T
) => T | void
customDimensions?: (
dimensions: { window: ScaledSize; screen: ScaledSize }
) => { window: ScaledSize; screen: ScaledSize } | void

/**
* 加载并执行异步分包的方法。
Expand Down
53 changes: 36 additions & 17 deletions packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,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({})
Expand All @@ -19,30 +19,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()
Expand All @@ -53,7 +63,11 @@ Dimensions.addEventListener('change', ({ window, screen }) => {
global.__mpxPageStatusMap[navigation.pageId] = `resize${global.__mpxSizeCount}`
}
}
})
}
// 默认实现:不传参时通过 Dimensions 实时获取当前屏幕尺寸(拷贝一份防止原对象被外部修改)
global.notifyDimensionsChange = onDimensionsChange

Dimensions.addEventListener('change', onDimensionsChange)

// TODO: 1 目前测试鸿蒙下折叠屏screen固定为展开状态下屏幕尺寸,仅window会变化,且window包含状态栏高度
// TODO: 2 存在部分安卓折叠屏机型在折叠/展开切换时,Dimensions监听到的width/height尺寸错误,并触发多次问题
Expand Down Expand Up @@ -82,8 +96,13 @@ const empty = {}

const isNum = (v) => !isNaN(+v)

let dimensionsApplied = false
function formatValue (value, unitType) {
if (!dimensionsInfoInitialized) useDimensionsInfo(global.__mpxAppDimensionsInfo)
// 懒初始化:首次调用时将初始 dimensions 写入全局(触发 customDimensions 处理)
if (!dimensionsApplied) {
dimensionsApplied = true
applyDimensionsInfo(global.__mpxAppDimensionsInfo)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 首次样式计算前发生尺寸通知,会重复应用 customDimensions

dimensionsApplied 只在 formatValue() 中置为 true。如果此前收到原生 Dimensions change 事件或调用 notifyDimensionsChange(),onDimensionsChange() 已经应用了 customDimensions,但这里仍会对转换后的全局尺寸再次执行转换。

已用 PR 与基线对照复现:配置 customDimensions 为 dimensions => { dimensions.screen.width /= 2 },原始宽度 800,通知后宽度为 400,首次计算 750rpx 时却得到 200;基线在相同原生事件顺序下正确得到 400。这会导致布局与媒体查询使用错误尺寸,也影响已有的原生尺寸事件路径。

建议在 applyDimensionsInfo() 中统一维护初始化标记,恢复原实现“任何入口应用尺寸后均视为已初始化”的语义,并补充尺寸事件发生在首次样式计算前的回归测试。

}
if (unitType && typeof unit[unitType] === 'function') {
return unit[unitType](+value)
}
Expand Down
Loading