Skip to content

Commit 57cdec4

Browse files
author
yandadaFreedom
committed
fix: 修复 RN runtime 组件问题
1 parent 510ef89 commit 57cdec4

13 files changed

Lines changed: 104 additions & 62 deletions

File tree

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,7 @@ Mpx 输出 RN 内置支持了大部分常用的基础组件,详情见下方文
822822

823823
| 事件名 | 说明 |
824824
| --- | --- |
825-
| change | current 改变时会触发 change 事件,`event.detail = {current, source}` |
825+
| change | current 改变时会触发 change 事件,`event.detail = {current, source}``source``touch``autoplay` 或空字符串,分别表示用户滑动、自动播放或其他原因导致的切换 |
826826

827827
### swiper-item
828828

@@ -963,7 +963,7 @@ movable-view 的可移动区域。
963963

964964
| 事件名 | 说明 |
965965
| --- | --- |
966-
| change | checkbox-group 中选中项发生改变时触发 change 事件,`detail = { value: [ 选中的 checkbox 的 value 的数组 ] } ` |
966+
| change | checkbox-group 中选中项发生改变时触发 change 事件,`event.type = 'change'``event.detail = { value: [选中的 checkbox 的 value 的数组] }` |
967967

968968
### radio
969969

@@ -986,7 +986,7 @@ movable-view 的可移动区域。
986986

987987
| 事件名 | 说明 |
988988
| --- | --- |
989-
| change | radio-group 中选中项发生改变时触发 change 事件,`detail = { value: [ 选中的 radio 的 value 的数组 ] }` |
989+
| change | radio-group 中选中项发生改变时触发 change 事件,`event.type = 'change'``event.detail = { value: 选中的 radio 的 value }` |
990990

991991
### form
992992

@@ -999,7 +999,7 @@ movable-view 的可移动区域。
999999
| 事件名 | 说明 |
10001000
| --- | --- |
10011001
| submit | 携带 form 中的数据触发 submit 事件,`event.detail = {value : {'name': 'value'} }` |
1002-
| reset | 表单重置时会触发 reset 事件 |
1002+
| reset | 表单重置时会触发 reset 事件`event.type = 'reset'` |
10031003

10041004
### input
10051005

@@ -1162,7 +1162,7 @@ movable-view 的可移动区域。
11621162

11631163
| 事件名 | 说明 |
11641164
| ---------- | ------------------------------------------------------ |
1165-
| cancel | 取消选择时触发 |
1165+
| cancel | 取消选择时触发 cancel 事件,`event.type = 'cancel'` |
11661166
| change | value 改变时触发 change 事件,`event.detail = {value}` |
11671167

11681168
#### 普通选择器:mode = selector
@@ -1352,7 +1352,7 @@ level 有效值:
13521352
| 事件名 | 说明 |
13531353
| --- | --- |
13541354
| initdone | 相机初始化完成时触发,`event.detail = { maxZoom }` |
1355-
| stop | 摄像头在非正常终止时触发 |
1355+
| stop | 摄像头在非正常终止时触发 stop 事件,`event.type = 'stop'` |
13561356
| error | 相机发生错误时触发 |
13571357
| scancode |`scanCode` 模式下识别到二维码时触发,`event.detail = { result, type, scanArea }` |
13581358

@@ -1398,13 +1398,13 @@ level 有效值:
13981398
| --- | --- |
13991399
| play | 当开始/继续播放时触发 play 事件 |
14001400
| pause | 当暂停播放时触发 pause 事件 |
1401-
| ended | 当播放到末尾时触发 ended 事件 |
1401+
| ended | 当播放到末尾时触发 ended 事件`event.type = 'ended'` |
14021402
| timeupdate | 播放进度变化时触发,`event.detail = {currentTime, duration}` |
14031403
| fullscreenchange | 视频进入和退出全屏时触发,`event.detail = {fullScreen` } |
14041404
| waiting | 视频出现缓冲时触发 |
1405-
| error | 视频播放出错时触发 |
1405+
| error | 视频播放出错时触发 error 事件,`event.type = 'error'` |
14061406
| loadedmetadata | 视频元数据加载完成时触发。`event.detail = {width, height, duration}` |
1407-
| controlstoggle | 切换 controls 显示隐藏时触发`event.detail = {show}` |
1407+
| controlstoggle | 切换 controls 显示隐藏时触发 controlstoggle 事件,`event.type = 'controlstoggle'``event.detail = {show}` |
14081408
| seekcomplete | seek 完成时触发 |
14091409

14101410
#### 注意事项

docs-vitepress/guide/rn/component.md

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
- #### 基础组件
88
**容器组件**[view](#view) · [scroll-view](#scroll-view) · [swiper](#swiper) · [swiper-item](#swiper-item) · [movable-area](#movable-area) · [movable-view](#movable-view) · [root-portal](#root-portal) · [sticky-section](#sticky-section) · [sticky-header](#sticky-header) · [cover-view](#cover-view)
99

10-
**媒体组件**[image](#image) · [video](#video) · [canvas](#canvas)
10+
**媒体组件**[image](#image) · [video](#video) · [canvas](#canvas) · [camera](#camera)
1111

1212
**表单组件**[input](#input) · [textarea](#textarea) · [button](#button) · [checkbox](#checkbox) · [checkbox-group](#checkbox-group) · [radio](#radio) · [radio-group](#radio-group) · [switch](#switch) · [picker](#picker) · [picker-view](#picker-view) · [picker-view-column](#picker-view-column) · [form](#form) · [label](#label)
1313

@@ -181,7 +181,7 @@
181181

182182
| 事件名 | 说明 |
183183
| ----------------| ------------------ |
184-
| change| current 改变时会触发 change 事件,`event.detail = {current, source}`|
184+
| change| current 改变时会触发 change 事件,`event.detail = {current, source}``source``touch``autoplay` 或空字符串,分别表示用户滑动、自动播放或其他原因导致的切换 |
185185

186186
### swiper-item
187187
仅可放置在swiper组件中,宽高自动设置为100%。
@@ -320,7 +320,7 @@ movable-view的可移动区域。
320320

321321
| 事件名 | 说明 |
322322
| ----------------| ------------------ |
323-
| change | checkbox-group 中选中项发生改变时触发 change 事件,`detail = { value: [ 选中的 checkbox 的 value 的数组 ] } `|
323+
| change | checkbox-group 中选中项发生改变时触发 change 事件,`event.type = 'change'``event.detail = { value: [选中的 checkbox 的 value 的数组] }` |
324324

325325

326326
### radio
@@ -345,7 +345,7 @@ movable-view的可移动区域。
345345

346346
| 事件名 | 说明 |
347347
| ----------------| ------------------ |
348-
| change | radio-group 中选中项发生改变时触发 change 事件,`detail = { value: [ 选中的 radio 的 value 的数组 ] }` |
348+
| change | radio-group 中选中项发生改变时触发 change 事件,`event.type = 'change'``event.detail = { value: 选中的 radio 的 value }` |
349349

350350

351351
### form
@@ -358,7 +358,7 @@ movable-view的可移动区域。
358358
| 事件名 | 说明 |
359359
| ---------- | --------------------------------------------------- |
360360
| submit | 携带 form 中的数据触发 submit 事件,`event.detail = {value : {'name': 'value'} }` |
361-
| reset | 表单重置时会触发 reset 事件 |
361+
| reset | 表单重置时会触发 reset 事件`event.type = 'reset'` |
362362

363363

364364
### input
@@ -517,7 +517,7 @@ movable-view的可移动区域。
517517

518518
| 事件名 | 说明 |
519519
| ----------------| ----------------------------------------------------|
520-
| cancel | 取消选择时触发 |
520+
| cancel | 取消选择时触发 cancel 事件,`event.type = 'cancel'` |
521521
| change | value 改变时触发 change 事件,`event.detail = {value}` |
522522

523523
#### 普通选择器:mode = selector {#mode-selector}
@@ -658,6 +658,42 @@ API
658658
> - canvas 的实现主要借助于 PostMessage 方式与 webview 容器通信进行绘制,所以对于严格依赖方法执行时机的场景,如调用 drawImage 绘图,再通过 getImageData 获取图片数据的场景,调用时需要使用 await 等方式来保证方法的执行时机
659659
> - 通过 Canvas.createImage 画图,图片的链接不能有特殊字符,安卓手机可能会 load 失败
660660
661+
### camera
662+
663+
系统相机。
664+
665+
#### 属性 {#camera-props}
666+
667+
| 属性名 | 类型 | 默认值 | 说明 |
668+
| --- | --- | --- | --- |
669+
| mode | string | `normal` | 应用模式,可选值为 `normal``scanCode` |
670+
| resolution | string | `medium` | 分辨率,可选值为 `low``medium``high` |
671+
| device-position | string | `back` | 摄像头朝向,可选值为 `front``back` |
672+
| flash | string | `auto` | 闪光灯,可选值为 `auto``on``off` |
673+
| frame-size | string | `medium` | 指定期望的相机帧数据尺寸,可选值为 `small``medium``large` |
674+
675+
#### 事件 {#camera-events}
676+
677+
| 事件名 | 说明 |
678+
| --- | --- |
679+
| initdone | 相机初始化完成时触发,`event.detail = { maxZoom }` |
680+
| stop | 摄像头在非正常终止时触发 stop 事件,`event.type = 'stop'` |
681+
| error | 相机发生错误时触发 |
682+
| scancode |`scanCode` 模式下识别到二维码时触发,`event.detail = { result, type, scanArea }` |
683+
684+
#### API
685+
686+
| 方法名 | 说明 |
687+
| --- | --- |
688+
| setZoom | 设置缩放级别 |
689+
| takePhoto | 拍照,仅支持在 `normal` 模式中使用 |
690+
| startRecord | 开始录像 |
691+
| stopRecord | 结束录像 |
692+
693+
> [!tip] 注意
694+
>
695+
> camera 组件基于第三方库 `react-native-vision-camera` 实现,需要容器安装该依赖并完成相机权限配置。
696+
661697
### video
662698
视频
663699

@@ -688,13 +724,13 @@ API
688724
| ----------------| --------------------------------------------------- |
689725
| play | 当开始/继续播放时触发play事件 |
690726
| pause | 当暂停播放时触发 pause 事件 |
691-
| ended | 当播放到末尾时触发 ended 事件 |
727+
| ended | 当播放到末尾时触发 ended 事件`event.type = 'ended'` |
692728
| timeupdate | 播放进度变化时触发,`event.detail = {currentTime, duration}` |
693729
| fullscreenchange | 视频进入和退出全屏时触发,`event.detail = {fullScreen` } |
694730
| waiting | 视频出现缓冲时触发 |
695-
| error | 视频播放出错时触发 |
731+
| error | 视频播放出错时触发 error 事件,`event.type = 'error'` |
696732
| loadedmetadata | 视频元数据加载完成时触发。`event.detail = {width, height, duration}` |
697-
| controlstoggle | 切换 controls 显示隐藏时触发`event.detail = {show}` |
733+
| controlstoggle | 切换 controls 显示隐藏时触发 controlstoggle 事件,`event.type = 'controlstoggle'``event.detail = {show}` |
698734
| seekcomplete | seek 完成时触发 |
699735

700736
> [!tip] 注意

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ interface CameraProps {
2020
flash?: 'auto' | 'on' | 'off'
2121
'frame-size'?: 'small' | 'medium' | 'large'
2222
style?: Record<string, any>
23-
bindstop?: () => void
23+
bindstop?: (event: Record<string, any>) => void
2424
binderror?: (error: { message: string }) => void
2525
bindinitdone?: (result: { type: string, data: string }) => void
2626
bindscancode?: (result: { type: string, data: string }) => void
@@ -177,7 +177,7 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
177177
}, [bindinitdone, maxZoom])
178178

179179
const onStopped = useCallback(() => {
180-
bindstop && bindstop()
180+
bindstop && bindstop(getCustomEvent('stop', {}, { layoutRef }))
181181
}, [bindstop])
182182

183183
const camera: CameraRef = useMemo(() => ({

packages/webpack-plugin/lib/runtime/components/react/mpx-canvas/Image.ts

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ export class Image {
1313
canvas: any;
1414
width: number;
1515
height: number;
16-
private _loadListener: any;
17-
private _errorListener: any;
16+
private _removeLoadListener?: () => void;
17+
private _removeErrorListener?: () => void;
1818
private _onload: ((...args: any[]) => void);
1919
private _onerror: ((...args: any[]) => void);
2020
[key: string]: any;
@@ -70,12 +70,8 @@ export class Image {
7070

7171
set onload (callback: ((...args: any[]) => void)) {
7272
this._onload = callback
73-
if (this._loadListener) {
74-
this.canvas.removeMessageListener(this._loadListener)
75-
}
76-
if (callback) {
77-
this._loadListener = this.addEventListener('load', callback)
78-
}
73+
this._removeLoadListener?.()
74+
this._removeLoadListener = callback ? this.addEventListener('load', callback) : undefined
7975
}
8076

8177
get onload (): ((...args: any[]) => void) {
@@ -84,12 +80,8 @@ export class Image {
8480

8581
set onerror (callback: ((...args: any[]) => void)) {
8682
this._onerror = callback
87-
if (this._errorListener) {
88-
this.canvas.removeMessageListener(this._errorListener)
89-
}
90-
if (callback) {
91-
this._errorListener = this.addEventListener('error', callback)
92-
}
83+
this._removeErrorListener?.()
84+
this._removeErrorListener = callback ? this.addEventListener('error', callback) : undefined
9385
}
9486

9587
get onerror () : ((...args: any[]) => void) {

packages/webpack-plugin/lib/runtime/components/react/mpx-canvas/index.tsx

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,10 @@ const _Canvas = forwardRef<HandlerRef<CanvasProps & View, CanvasProps>, CanvasPr
200200
}
201201

202202
const removeMessageListener = (listener: any) => {
203-
canvasRef.current.listeners.splice(canvasRef.current.listeners.indexOf(listener), 1)
203+
const index = canvasRef.current.listeners.indexOf(listener)
204+
if (index > -1) {
205+
canvasRef.current.listeners.splice(index, 1)
206+
}
204207
}
205208

206209
const onMessage = useCallback((e: { nativeEvent: { data: string } }) => {
@@ -288,22 +291,22 @@ const _Canvas = forwardRef<HandlerRef<CanvasProps & View, CanvasProps>, CanvasPr
288291
allowUniversalAccessFromFileURLs: true
289292
})
290293
)
294+
} else {
295+
canvasComponent = createElement(View, innerProps, createElement(WebView, {
296+
ref: (element: WebViewInstance | null) => {
297+
if (canvasRef.current) {
298+
canvasRef.current.webview = element
299+
}
300+
},
301+
style: [stylesheet.webview, { height, width }],
302+
source: { html },
303+
originWhitelist: originWhitelist,
304+
onMessage: onMessage,
305+
onLoad: onLoad,
306+
scrollEnabled: false
307+
}))
291308
}
292309

293-
canvasComponent = createElement(View, innerProps, createElement(WebView, {
294-
ref: (element: WebViewInstance | null) => {
295-
if (canvasRef.current) {
296-
canvasRef.current.webview = element
297-
}
298-
},
299-
style: [stylesheet.webview, { height, width }],
300-
source: { html },
301-
originWhitelist: originWhitelist,
302-
onMessage: onMessage,
303-
onLoad: onLoad,
304-
scrollEnabled: false
305-
}))
306-
307310
if (hasPositionFixed) {
308311
canvasComponent = createElement(Portal, null, canvasComponent)
309312
}

packages/webpack-plugin/lib/runtime/components/react/mpx-checkbox-group.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ const CheckboxGroup = forwardRef<
138138
bindchange &&
139139
bindchange(
140140
getCustomEvent(
141-
'tap',
141+
'change',
142142
evt,
143143
{
144144
layoutRef,

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ interface FormProps {
2323
value: any
2424
}
2525
}) => void
26-
bindreset?: () => void
26+
bindreset?: (evt: Record<string, any>) => void
2727
}
2828

2929
const _Form = forwardRef<HandlerRef<View, FormProps>, FormProps>((fromProps: FormProps, ref): JSX.Element => {
@@ -98,7 +98,7 @@ const _Form = forwardRef<HandlerRef<View, FormProps>, FormProps>((fromProps: For
9898

9999
const reset = () => {
100100
const { bindreset } = propsRef.current
101-
bindreset && bindreset()
101+
bindreset && bindreset(getCustomEvent('reset', {}, { layoutRef }, propsRef.current))
102102
formValuesMap.forEach(item => item.resetValue())
103103
}
104104
return {

packages/webpack-plugin/lib/runtime/components/react/mpx-picker/date.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ const valueChanged2Obj = (currentObj: FormatObj, value: number[], limit = 3) =>
121121
const rangeArr = currentObj.rangeArr
122122

123123
if (limit === 3 && (currentValue[0] !== value[0] || currentValue[1] !== value[1])) {
124-
const days = daysInMonth(value[0], value[1] + 1)
124+
const days = daysInMonth(value[0] + START_YEAR, value[1] + 1)
125125
rangeArr[2] = days
126126
const maxIndex = days.length - 1
127127
if (value[2] > maxIndex) {

packages/webpack-plugin/lib/runtime/components/react/mpx-picker/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ const Picker = forwardRef<HandlerRef<View, PickerProps>, PickerProps>(
250250
}
251251

252252
const onCancel = () => {
253-
bindcancel?.()
253+
bindcancel?.(getCustomEvent('cancel', {}, { layoutRef }, props))
254254
hide()
255255
}
256256

packages/webpack-plugin/lib/runtime/components/react/mpx-radio-group.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ const radioGroup = forwardRef<
118118
bindchange &&
119119
bindchange(
120120
getCustomEvent(
121-
'tap',
121+
'change',
122122
evt,
123123
{
124124
layoutRef,

0 commit comments

Comments
 (0)