Skip to content

Commit 6bda5ac

Browse files
authored
Merge pull request #2482 from didi/rn-box-sizing
fix rn box-sizing
2 parents 172e48e + 8b85f5f commit 6bda5ac

7 files changed

Lines changed: 47 additions & 6 deletions

File tree

.agents/skills/mpx2rn/references/rn-style-reference.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ Mpx 在 RN 平台支持 CSS 背景图及渐变背景,框架会自动处理样
443443
| `min-width` / `min-height` | `length` \| `%` | - | 最小尺寸 |
444444
| `max-width` / `max-height` | `length` \| `%` | - | 最大尺寸 |
445445
| `aspect-ratio` | `auto` \| `number` \| `width / height` | - | 宽高比 |
446-
| `box-sizing` | `border-box` \| `content-box` | `border-box` | 盒模型 |
446+
| `box-sizing` | `border-box` \| `content-box` | `content-box` | 盒模型,RN 原始默认值为 `border-box`,Mpx 中为了跨端表现一致统一默认值为 `content-box`,可通过 `mpx.config.rnConfig.defaultBoxSizing` 配置默认值 |
447447
| `overflow` | `visible` \| `hidden` \| `scroll` | `visible` | 溢出控制 |
448448

449449
### 间距 (Margin/Padding)

packages/core/@types/index.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,14 @@ export interface WebviewConfig {
279279
* 输出为 ReactNative 时使用的特殊配置,用于与容器进行功能桥接
280280
*/
281281
export interface RnConfig {
282+
/**
283+
* RN 节点未显式声明 box-sizing 时使用的默认盒模型。
284+
*
285+
* 默认值为 content-box,用于对齐小程序 / Web 的默认行为。
286+
* 如需保留 RN 原始默认盒模型,可配置为 border-box。
287+
*/
288+
defaultBoxSizing?: 'border-box' | 'content-box'
289+
282290
/**
283291
* 当导航状态发生变化时触发,例如页面跳转、返回等。
284292
*

packages/core/src/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,9 @@ Mpx.config = {
154154
/**
155155
* react-native 相关配置,用于挂载事件等,如 onShareAppMessage
156156
*/
157-
rnConfig: {}
157+
rnConfig: {
158+
defaultBoxSizing: 'content-box'
159+
}
158160
}
159161

160162
init(Mpx)

packages/webpack-plugin/lib/runtime/components/react/mpx-simple-text.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Text, TextProps } from 'react-native'
22
import { JSX, createElement } from 'react'
33
import useInnerProps from './getInnerListeners'
4-
import { extendObject } from './utils'
4+
import { extendObject, transformBoxSizing } from './utils'
55

66
const SimpleText = (props: TextProps): JSX.Element => {
77
const {
@@ -14,7 +14,8 @@ const SimpleText = (props: TextProps): JSX.Element => {
1414
{},
1515
props,
1616
{
17-
allowFontScaling
17+
allowFontScaling,
18+
style: transformBoxSizing(extendObject({}, props.style || {}))
1819
}
1920
)
2021
)

packages/webpack-plugin/lib/runtime/components/react/mpx-simple-view.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { View, ViewProps, TextStyle } from 'react-native'
22
import { createElement } from 'react'
3-
import { splitProps, splitStyle, wrapChildren, extendObject } from './utils'
3+
import { splitProps, splitStyle, wrapChildren, extendObject, transformBoxSizing } from './utils'
44
import useInnerProps from './getInnerListeners'
55

66
const SimpleView = (simpleViewProps: ViewProps): JSX.Element => {
@@ -13,7 +13,7 @@ const SimpleView = (simpleViewProps: ViewProps): JSX.Element => {
1313
{},
1414
props,
1515
{
16-
style: innerStyle
16+
style: transformBoxSizing(extendObject({}, innerStyle))
1717
}
1818
)
1919
)

packages/webpack-plugin/lib/runtime/components/react/utils.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ export const DEFAULT_FONT_SIZE = 16
1818
export const HIDDEN_STYLE = {
1919
opacity: 0
2020
}
21+
export const DEFAULT_BOX_SIZING_STYLE = {
22+
boxSizing: 'content-box'
23+
}
2124

2225
declare const __mpx_mode__: 'ios' | 'android' | 'harmony'
2326

@@ -43,6 +46,13 @@ const safeAreaInsetMap: Record<string, 'top' | 'right' | 'bottom' | 'left'> = {
4346

4447
export const extendObject = Object.assign
4548

49+
export function transformBoxSizing (style: Record<string, any> = {}) {
50+
if (style.boxSizing === undefined) {
51+
style.boxSizing = global.__mpx?.config?.rnConfig?.defaultBoxSizing ?? DEFAULT_BOX_SIZING_STYLE.boxSizing
52+
}
53+
return style
54+
}
55+
4656
function getSafeAreaInset (name: string, navigation: Record<string, any> | undefined) {
4757
const insets = extendObject({}, initialWindowMetrics?.insets, navigation?.insets)
4858
return insets[safeAreaInsetMap[name]]
@@ -552,6 +562,7 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
552562
transformBoxShadow(normalStyle)
553563
// transform 字符串格式转化数组格式(先转数组再处理css var)
554564
transformTransform(normalStyle)
565+
transformBoxSizing(normalStyle)
555566

556567
return {
557568
hasVarDec,

packages/webpack-plugin/test/platform/wx/style-helper-rn.spec.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,5 +320,24 @@ describe('React Native style validation for CSS variables', () => {
320320
expect(result).toEqual({})
321321
expect(config.error).toHaveBeenCalledTimes(2)
322322
})
323+
324+
test('should keep explicit box-sizing values', () => {
325+
const css = '.content { box-sizing: content-box; } .border { box-sizing: border-box; }'
326+
const config = createConfig()
327+
328+
const result = getClassMap({
329+
content: css,
330+
filename: 'test.css',
331+
...config
332+
})
333+
334+
expect(result.content).toEqual({
335+
boxSizing: '"content-box"'
336+
})
337+
expect(result.border).toEqual({
338+
boxSizing: '"border-box"'
339+
})
340+
expect(config.error).not.toHaveBeenCalled()
341+
})
323342
})
324343
})

0 commit comments

Comments
 (0)