@mpxjs/webpack-plugin 2.10.6-beta.7 → 2.10.7-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,192 +1,79 @@
1
- import { useState, ComponentType, useEffect, useCallback, useRef, ReactNode, createElement } from 'react'
2
- import { View, Image, StyleSheet, Text, TouchableOpacity } from 'react-native'
3
- import FastImage from '@d11/react-native-fast-image'
1
+ import { useState, ComponentType, useEffect, useCallback, useRef } from 'react'
2
+ import { DefaultFallback, DefaultLoading, PageWrapper } from './AsyncContainer'
3
+ import type { DefaultFallbackProps } from './AsyncContainer'
4
4
 
5
5
  const asyncChunkMap = new Map()
6
6
 
7
- const styles = StyleSheet.create({
8
- container: {
9
- flex: 1,
10
- padding: 20,
11
- backgroundColor: '#fff'
12
- },
13
- loadingImage: {
14
- width: 100,
15
- height: 100,
16
- marginTop: 220,
17
- alignSelf: 'center'
18
- },
19
- buttonText: {
20
- color: '#fff',
21
- fontSize: 16,
22
- fontWeight: '500',
23
- textAlign: 'center'
24
- },
25
- errorImage: {
26
- marginTop: 80,
27
- width: 220,
28
- aspectRatio: 1,
29
- alignSelf: 'center'
30
- },
31
- errorText: {
32
- fontSize: 16,
33
- textAlign: 'center',
34
- color: '#333',
35
- marginBottom: 20
36
- },
37
- retryButton: {
38
- position: 'absolute',
39
- bottom: 54,
40
- left: 20,
41
- right: 20,
42
- backgroundColor: '#fff',
43
- paddingVertical: 15,
44
- borderRadius: 30,
45
- marginTop: 40,
46
- borderWidth: 1,
47
- borderColor: '#FF5F00'
48
- },
49
- retryButtonText: {
50
- color: '#FF5F00',
51
- fontSize: 16,
52
- fontWeight: '500',
53
- textAlign: 'center'
54
- }
55
- })
56
-
57
- interface LayoutViewProps {
58
- children: ReactNode
59
- }
60
-
61
- interface AsyncModule {
62
- __esModule: boolean
63
- default: ReactNode
64
- }
65
-
66
- interface DefaultFallbackProps {
67
- onReload: () => void
68
- }
69
-
70
- const DefaultFallback = ({ onReload }: DefaultFallbackProps) => {
71
- return (
72
- <View style={styles.container}>
73
- <Image
74
- source={{
75
- uri: 'https://dpubstatic.udache.com/static/dpubimg/Vak5mZvezPpKV5ZJI6P9b_drn-fallbak.png'
76
- }}
77
- style={styles.errorImage}
78
- resizeMode="contain"
79
- />
80
- <Text style={styles.errorText}>网络出了点问题,请查看网络环境</Text>
81
- <TouchableOpacity
82
- style={styles.retryButton}
83
- onPress={onReload}
84
- activeOpacity={0.7}
85
- >
86
- <Text style={styles.retryButtonText}>点击重试</Text>
87
- </TouchableOpacity>
88
- </View>
89
- )
90
- }
91
-
92
- const LayoutView = (props: LayoutViewProps) => {
93
- return (
94
- <View style={{ flex: 1 }} collapsable={false}>{props.children}</View>
95
- )
96
- }
97
-
98
- const DefaultLoading = () => {
99
- return (
100
- <View style={styles.container}>
101
- <FastImage
102
- style={styles.loadingImage}
103
- source={{
104
- uri: 'https://dpubstatic.udache.com/static/dpubimg/439jiCVOtNOnEv9F2LaDs_loading.gif'
105
- }}
106
- resizeMode={FastImage.resizeMode.contain}
107
- ></FastImage>
108
- </View>
109
- )
110
- }
111
-
112
- interface AsyncSuspenseProps {
7
+ interface props {
113
8
  type: 'component' | 'page'
114
9
  chunkName: string
115
- moduleId: string
116
- innerProps: any,
10
+ request: string
11
+ props: any,
117
12
  loading: ComponentType<unknown>
118
13
  fallback: ComponentType<unknown>
119
- getChildren: () => Promise<AsyncModule>
14
+ getChildren: () => Promise<unknown>
120
15
  }
121
16
 
122
- type ComponentStauts = 'pending' | 'error' | 'loaded'
123
-
124
- const AsyncSuspense: React.FC<AsyncSuspenseProps> = ({
125
- type,
126
- innerProps,
127
- chunkName,
128
- moduleId,
129
- loading,
130
- fallback,
131
- getChildren
132
- }) => {
133
- const [status, setStatus] = useState<ComponentStauts>('pending')
134
- const chunkLoaded = asyncChunkMap.has(moduleId)
135
- const loadChunkPromise = useRef<null | Promise<AsyncModule>>(null)
17
+ const AsyncSuspense: React.FC<props> = ({ type, props, chunkName, request, loading, fallback, getChildren }) => {
18
+ const [status, setStatus] = useState('pending')
19
+ const loaded = asyncChunkMap.has(request)
20
+ const [, setKey] = useState(0)
21
+ const chunkPromise = useRef<null | Promise<unknown>>(null)
136
22
 
137
23
  const reloadPage = useCallback(() => {
24
+ setKey((preV) => preV + 1)
25
+ console.log('[mpxAsyncSuspense]: reload page')
138
26
  setStatus('pending')
139
27
  }, [])
140
28
 
141
29
  useEffect(() => {
142
- let cancelled = false
143
- if (!chunkLoaded && status === 'pending') {
144
- if (loadChunkPromise.current) {
145
- loadChunkPromise
146
- .current.then((m: AsyncModule) => {
147
- if (cancelled) return
148
- asyncChunkMap.set(moduleId, m.__esModule ? m.default : m)
149
- setStatus('loaded')
150
- })
151
- .catch((e) => {
152
- if (cancelled) return
153
- if (type === 'component') {
154
- global.onLazyLoadError({
155
- type: 'subpackage',
156
- subpackage: [chunkName],
157
- errMsg: `loadSubpackage: ${e.type}`
158
- })
159
- }
160
- loadChunkPromise.current = null
161
- setStatus('error')
162
- })
163
- }
164
- }
165
-
166
- return () => {
167
- cancelled = true
30
+ if (!loaded && status === 'pending') {
31
+ // todo 清楚副作用?
32
+ console.log('the current :', chunkPromise.current)
33
+ chunkPromise.current!
34
+ .then((m: any) => {
35
+ console.log('[mpxAsyncSuspense]: load sucess')
36
+ asyncChunkMap.set(request, m.__esModule ? m.default : m)
37
+ setStatus('loaded')
38
+ })
39
+ .catch((e) => {
40
+ if (type === 'component') {
41
+ console.log(11111, e)
42
+ global.onLazyLoadError({
43
+ type: 'subpackage',
44
+ subpackage: [chunkName],
45
+ errMsg: `loadSubpackage: ${e.type}`
46
+ })
47
+ }
48
+ console.log('[mpxAsyncSuspense]: load eror', e)
49
+ chunkPromise.current = null
50
+ setStatus('error')
51
+ })
168
52
  }
169
- }, [status])
53
+ })
170
54
 
171
- if (chunkLoaded) {
172
- const Comp = asyncChunkMap.get(moduleId)
173
- return createElement(Comp, innerProps)
55
+ if (loaded) {
56
+ const Comp = asyncChunkMap.get(request)
57
+ return <Comp {...props}></Comp>
174
58
  } else if (status === 'error') {
59
+ console.log('the status is:', status)
175
60
  if (type === 'page') {
176
- const Fallback =
177
- (fallback as ComponentType<DefaultFallbackProps>) || DefaultFallback
178
- return createElement(LayoutView, null, createElement(Fallback, { onReload: reloadPage }))
61
+ const Fallback = fallback as ComponentType<DefaultFallbackProps> || DefaultFallback
62
+ return <><PageWrapper><Fallback onReload={reloadPage}></Fallback></PageWrapper></>
179
63
  } else {
180
- return createElement(fallback, innerProps)
64
+ const Fallback = loading
65
+ return <Fallback {...props}></Fallback>
181
66
  }
182
67
  } else {
183
- if (!loadChunkPromise.current) {
184
- loadChunkPromise.current = getChildren()
68
+ if (!chunkPromise.current) {
69
+ chunkPromise.current = getChildren()
185
70
  }
186
71
  if (type === 'page') {
187
- return createElement(LayoutView, null, createElement(loading || DefaultLoading))
72
+ const Fallback = loading || DefaultLoading
73
+ return <PageWrapper><Fallback /></PageWrapper>
188
74
  } else {
189
- return createElement(fallback, innerProps)
75
+ const Fallback = loading
76
+ return <Fallback {...props}></Fallback>
190
77
  }
191
78
  }
192
79
  }
@@ -0,0 +1,160 @@
1
+ import { Component, Suspense } from 'react';
2
+ import { View, Text, Image, StyleSheet, TouchableOpacity } from 'react-native';
3
+ import FastImage from '@d11/react-native-fast-image';
4
+ import Animated, { useAnimatedStyle } from 'react-native-reanimated';
5
+ export const PageWrapper = ({ children }) => {
6
+ const animatedStyle = useAnimatedStyle(() => ({
7
+ transform: [{ translateY: -0 }],
8
+ flexBasis: 'auto',
9
+ flex: 1
10
+ }));
11
+ return (<Animated.View style={[
12
+ animatedStyle
13
+ ]}>
14
+ {children}
15
+ </Animated.View>);
16
+ };
17
+ const styles = StyleSheet.create({
18
+ container: {
19
+ flex: 1,
20
+ padding: 20,
21
+ backgroundColor: '#fff'
22
+ },
23
+ loadingImage: {
24
+ width: 100,
25
+ height: 100,
26
+ marginTop: 220,
27
+ alignSelf: 'center'
28
+ },
29
+ buttonText: {
30
+ color: '#fff',
31
+ fontSize: 16,
32
+ fontWeight: '500',
33
+ textAlign: 'center'
34
+ },
35
+ errorImage: {
36
+ marginTop: 80,
37
+ width: 220,
38
+ aspectRatio: 1,
39
+ alignSelf: 'center'
40
+ },
41
+ errorText: {
42
+ fontSize: 16,
43
+ textAlign: 'center',
44
+ color: '#333',
45
+ marginBottom: 20
46
+ },
47
+ retryButton: {
48
+ position: 'absolute',
49
+ bottom: 54,
50
+ left: 20,
51
+ right: 20,
52
+ backgroundColor: '#fff',
53
+ paddingVertical: 15,
54
+ borderRadius: 30,
55
+ marginTop: 40,
56
+ borderWidth: 1,
57
+ borderColor: '#FF5F00'
58
+ },
59
+ retryButtonText: {
60
+ color: '#FF5F00',
61
+ fontSize: 16,
62
+ fontWeight: '500',
63
+ textAlign: 'center'
64
+ }
65
+ });
66
+ export const DefaultLoading = () => {
67
+ return (<View style={styles.container}>
68
+ <FastImage style={styles.loadingImage} source={{ uri: 'https://dpubstatic.udache.com/static/dpubimg/439jiCVOtNOnEv9F2LaDs_loading.gif' }} resizeMode={FastImage.resizeMode.contain}></FastImage>
69
+ </View>);
70
+ };
71
+ export const DefaultFallback = ({ onReload }) => {
72
+ return (<View style={styles.container}>
73
+ <Image source={{ uri: 'https://dpubstatic.udache.com/static/dpubimg/Vak5mZvezPpKV5ZJI6P9b_drn-fallbak.png' }} style={styles.errorImage} resizeMode="contain"/>
74
+ <Text style={styles.errorText}>网络出了点问题,请查看网络环境</Text>
75
+ <TouchableOpacity style={styles.retryButton} onPress={onReload} activeOpacity={0.7}>
76
+ <Text style={styles.retryButtonText}>点击重试</Text>
77
+ </TouchableOpacity>
78
+ </View>);
79
+ };
80
+ export default class AsyncContainer extends Component {
81
+ suspenseFallback;
82
+ errorFallback;
83
+ constructor(props) {
84
+ super(props);
85
+ this.state = {
86
+ hasError: false,
87
+ key: 0
88
+ };
89
+ this.suspenseFallback = this.getSuspenseFallback();
90
+ this.errorFallback = this.getErrorFallback();
91
+ }
92
+ // render 阶段收集到的错误
93
+ static getDerivedStateFromError(error) {
94
+ if (error.name === 'ChunkLoadError') {
95
+ return {
96
+ hasError: true,
97
+ key: 0
98
+ };
99
+ }
100
+ else {
101
+ // 被外层捕获
102
+ throw error;
103
+ }
104
+ }
105
+ componentDidCatch(error) {
106
+ if (error.name === 'ChunkLoadError' && this.props.type === 'component') {
107
+ const request = error.request || '';
108
+ const subpackage = request.split('/').filter((i) => !!i)[0];
109
+ global.onLazyLoadError({
110
+ type: 'subpackage',
111
+ subpackage: [subpackage],
112
+ errMsg: `loadSubpackage: ${error.type}`
113
+ });
114
+ }
115
+ }
116
+ reloadPage() {
117
+ this.setState((prevState) => {
118
+ return {
119
+ hasError: false,
120
+ key: prevState.key + 1
121
+ };
122
+ });
123
+ }
124
+ getSuspenseFallback() {
125
+ if (this.props.type === 'page') {
126
+ const Fallback = this.props.loading || DefaultLoading;
127
+ return <Fallback />;
128
+ }
129
+ else {
130
+ const Fallback = this.props.loading;
131
+ return <Fallback {...this.props.props}></Fallback>;
132
+ }
133
+ }
134
+ getErrorFallback() {
135
+ if (this.props.type === 'page') {
136
+ const Fallback = this.props.fallback || DefaultFallback;
137
+ return <Fallback onReload={this.reloadPage.bind(this)}></Fallback>;
138
+ }
139
+ else {
140
+ const Fallback = this.props.loading;
141
+ return <Fallback {...this.props.props}></Fallback>;
142
+ }
143
+ }
144
+ render() {
145
+ if (this.state.hasError) {
146
+ if (this.props.type === 'component') {
147
+ return this.errorFallback;
148
+ }
149
+ else {
150
+ return (<PageWrapper>{this.errorFallback}</PageWrapper>);
151
+ }
152
+ }
153
+ else {
154
+ return (<Suspense fallback={this.suspenseFallback} key={this.state.key}>
155
+ {typeof this.props.children === 'function' ? this.props.children(this.props.props) : this.props.children}
156
+ {/* {this.props.children(this.props.props)} */}
157
+ </Suspense>);
158
+ }
159
+ }
160
+ }
@@ -1,136 +1,67 @@
1
- import { useState, useEffect, useCallback, useRef, createElement } from 'react';
2
- import { View, Image, StyleSheet, Text, TouchableOpacity } from 'react-native';
3
- import FastImage from '@d11/react-native-fast-image';
1
+ import { useState, useEffect, useCallback, useRef } from 'react';
2
+ import { DefaultFallback, DefaultLoading, PageWrapper } from './AsyncContainer';
4
3
  const asyncChunkMap = new Map();
5
- const styles = StyleSheet.create({
6
- container: {
7
- flex: 1,
8
- padding: 20,
9
- backgroundColor: '#fff'
10
- },
11
- loadingImage: {
12
- width: 100,
13
- height: 100,
14
- marginTop: 220,
15
- alignSelf: 'center'
16
- },
17
- buttonText: {
18
- color: '#fff',
19
- fontSize: 16,
20
- fontWeight: '500',
21
- textAlign: 'center'
22
- },
23
- errorImage: {
24
- marginTop: 80,
25
- width: 220,
26
- aspectRatio: 1,
27
- alignSelf: 'center'
28
- },
29
- errorText: {
30
- fontSize: 16,
31
- textAlign: 'center',
32
- color: '#333',
33
- marginBottom: 20
34
- },
35
- retryButton: {
36
- position: 'absolute',
37
- bottom: 54,
38
- left: 20,
39
- right: 20,
40
- backgroundColor: '#fff',
41
- paddingVertical: 15,
42
- borderRadius: 30,
43
- marginTop: 40,
44
- borderWidth: 1,
45
- borderColor: '#FF5F00'
46
- },
47
- retryButtonText: {
48
- color: '#FF5F00',
49
- fontSize: 16,
50
- fontWeight: '500',
51
- textAlign: 'center'
52
- }
53
- });
54
- const DefaultFallback = ({ onReload }) => {
55
- return (<View style={styles.container}>
56
- <Image source={{
57
- uri: 'https://dpubstatic.udache.com/static/dpubimg/Vak5mZvezPpKV5ZJI6P9b_drn-fallbak.png'
58
- }} style={styles.errorImage} resizeMode="contain"/>
59
- <Text style={styles.errorText}>网络出了点问题,请查看网络环境</Text>
60
- <TouchableOpacity style={styles.retryButton} onPress={onReload} activeOpacity={0.7}>
61
- <Text style={styles.retryButtonText}>点击重试</Text>
62
- </TouchableOpacity>
63
- </View>);
64
- };
65
- const LayoutView = (props) => {
66
- return (<View style={{ flex: 1 }} collapsable={false}>{props.children}</View>);
67
- };
68
- const DefaultLoading = () => {
69
- return (<View style={styles.container}>
70
- <FastImage style={styles.loadingImage} source={{
71
- uri: 'https://dpubstatic.udache.com/static/dpubimg/439jiCVOtNOnEv9F2LaDs_loading.gif'
72
- }} resizeMode={FastImage.resizeMode.contain}></FastImage>
73
- </View>);
74
- };
75
- const AsyncSuspense = ({ type, innerProps, chunkName, moduleId, loading, fallback, getChildren }) => {
4
+ const AsyncSuspense = ({ type, props, chunkName, request, loading, fallback, getChildren }) => {
76
5
  const [status, setStatus] = useState('pending');
77
- const chunkLoaded = asyncChunkMap.has(moduleId);
78
- const loadChunkPromise = useRef(null);
6
+ const loaded = asyncChunkMap.has(request);
7
+ const [, setKey] = useState(0);
8
+ const chunkPromise = useRef(null);
79
9
  const reloadPage = useCallback(() => {
10
+ setKey((preV) => preV + 1);
11
+ console.log('[mpxAsyncSuspense]: reload page');
80
12
  setStatus('pending');
81
13
  }, []);
82
14
  useEffect(() => {
83
- let cancelled = false;
84
- if (!chunkLoaded && status === 'pending') {
85
- if (loadChunkPromise.current) {
86
- loadChunkPromise
87
- .current.then((m) => {
88
- if (cancelled)
89
- return;
90
- asyncChunkMap.set(moduleId, m.__esModule ? m.default : m);
91
- setStatus('loaded');
92
- })
93
- .catch((e) => {
94
- if (cancelled)
95
- return;
96
- if (type === 'component') {
97
- global.onLazyLoadError({
98
- type: 'subpackage',
99
- subpackage: [chunkName],
100
- errMsg: `loadSubpackage: ${e.type}`
101
- });
102
- }
103
- loadChunkPromise.current = null;
104
- setStatus('error');
105
- });
106
- }
15
+ if (!loaded && status === 'pending') {
16
+ // todo 清楚副作用?
17
+ console.log('the current :', chunkPromise.current);
18
+ chunkPromise.current
19
+ .then((m) => {
20
+ console.log('[mpxAsyncSuspense]: load sucess');
21
+ asyncChunkMap.set(request, m.__esModule ? m.default : m);
22
+ setStatus('loaded');
23
+ })
24
+ .catch((e) => {
25
+ if (type === 'component') {
26
+ console.log(11111, e);
27
+ global.onLazyLoadError({
28
+ type: 'subpackage',
29
+ subpackage: [chunkName],
30
+ errMsg: `loadSubpackage: ${e.type}`
31
+ });
32
+ }
33
+ console.log('[mpxAsyncSuspense]: load eror', e);
34
+ chunkPromise.current = null;
35
+ setStatus('error');
36
+ });
107
37
  }
108
- return () => {
109
- cancelled = true;
110
- };
111
- }, [status]);
112
- if (chunkLoaded) {
113
- const Comp = asyncChunkMap.get(moduleId);
114
- return createElement(Comp, innerProps);
38
+ });
39
+ if (loaded) {
40
+ const Comp = asyncChunkMap.get(request);
41
+ return <Comp {...props}></Comp>;
115
42
  }
116
43
  else if (status === 'error') {
44
+ console.log('the status is:', status);
117
45
  if (type === 'page') {
118
46
  const Fallback = fallback || DefaultFallback;
119
- return createElement(LayoutView, null, createElement(Fallback, { onReload: reloadPage }));
47
+ return <><PageWrapper><Fallback onReload={reloadPage}></Fallback></PageWrapper></>;
120
48
  }
121
49
  else {
122
- return createElement(fallback, innerProps);
50
+ const Fallback = loading;
51
+ return <Fallback {...props}></Fallback>;
123
52
  }
124
53
  }
125
54
  else {
126
- if (!loadChunkPromise.current) {
127
- loadChunkPromise.current = getChildren();
55
+ if (!chunkPromise.current) {
56
+ chunkPromise.current = getChildren();
128
57
  }
129
58
  if (type === 'page') {
130
- return createElement(LayoutView, null, createElement(loading || DefaultLoading));
59
+ const Fallback = loading || DefaultLoading;
60
+ return <PageWrapper><Fallback /></PageWrapper>;
131
61
  }
132
62
  else {
133
- return createElement(fallback, innerProps);
63
+ const Fallback = loading;
64
+ return <Fallback {...props}></Fallback>;
134
65
  }
135
66
  }
136
67
  };
@@ -41,7 +41,7 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
41
41
  const hasLayoutRef = useRef(false);
42
42
  const propsRef = useRef({});
43
43
  propsRef.current = (props || {});
44
- const { x = 0, y = 0, inertia = false, disabled = false, animation = true, 'out-of-bounds': outOfBounds = false, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, direction = 'none', 'simultaneous-handlers': originSimultaneousHandlers = [], 'wait-for': waitFor = [], style = {}, bindtouchstart, catchtouchstart, bindhtouchmove, bindvtouchmove, bindtouchmove, catchhtouchmove, catchvtouchmove, catchtouchmove, bindtouchend, catchtouchend, bindchange } = props;
44
+ const { x = 0, y = 0, inertia = false, disabled = false, animation = true, 'out-of-bounds': outOfBounds = false, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, direction = 'none', 'simultaneous-handlers': originSimultaneousHandlers = [], 'wait-for': waitFor = [], style = {}, changeThrottleTime = 60, bindtouchstart, catchtouchstart, bindhtouchmove, bindvtouchmove, bindtouchmove, catchhtouchmove, catchvtouchmove, catchtouchmove, bindtouchend, catchtouchend, bindchange } = props;
45
45
  const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(Object.assign({}, style, styles.container), { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
46
46
  const navigation = useNavigation();
47
47
  const prevSimultaneousHandlersRef = useRef(originSimultaneousHandlers || []);
@@ -62,6 +62,7 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
62
62
  const isFirstTouch = useSharedValue(true);
63
63
  const touchEvent = useSharedValue('');
64
64
  const initialViewPosition = useSharedValue({ x: x || 0, y: y || 0 });
65
+ const lastChangeTime = useSharedValue(0);
65
66
  const MovableAreaLayout = useContext(MovableAreaContext);
66
67
  const simultaneousHandlers = flatGesture(originSimultaneousHandlers);
67
68
  const waitForHandlers = flatGesture(waitFor);
@@ -99,6 +100,15 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
99
100
  layoutRef
100
101
  }, propsRef.current));
101
102
  }, []);
103
+ // 节流版本的 change 事件触发
104
+ const handleTriggerChangeThrottled = useCallback(({ x, y, type }) => {
105
+ 'worklet';
106
+ const now = Date.now();
107
+ if (now - lastChangeTime.value >= changeThrottleTime) {
108
+ lastChangeTime.value = now;
109
+ runOnJS(handleTriggerChange)({ x, y, type });
110
+ }
111
+ }, [changeThrottleTime]);
102
112
  useEffect(() => {
103
113
  runOnUI(() => {
104
114
  if (offsetX.value !== x || offsetY.value !== y) {
@@ -354,7 +364,8 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
354
364
  }
355
365
  }
356
366
  if (bindchange) {
357
- runOnJS(handleTriggerChange)({
367
+ // 使用节流版本减少 runOnJS 调用
368
+ handleTriggerChangeThrottled({
358
369
  x: offsetX.value,
359
370
  y: offsetY.value
360
371
  });
@@ -56,6 +56,9 @@ const _RichText = forwardRef((props, ref) => {
56
56
  source: { html: generateHTML(html) },
57
57
  onMessage: (event) => {
58
58
  setWebViewHeight(+event.nativeEvent.data);
59
+ },
60
+ style: {
61
+ backgroundColor: 'transparent'
59
62
  }
60
63
  }));
61
64
  if (hasPositionFixed) {