@tarojs/plugin-framework-react 3.5.0-beta.4 → 3.5.0-theta.0
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.
- package/dist/api-loader.js +2 -2
- package/dist/api-loader.js.map +1 -1
- package/dist/index.js +244 -246
- package/dist/index.js.map +1 -1
- package/dist/runtime.js +620 -626
- package/dist/runtime.js.map +1 -1
- package/package.json +6 -5
- package/LICENSE +0 -21
package/dist/runtime.js
CHANGED
|
@@ -1,114 +1,114 @@
|
|
|
1
1
|
import { EMPTY_OBJ, isFunction, isArray, hooks, ensure } from '@tarojs/shared';
|
|
2
2
|
import { Current, getPageInstance, injectPageInstance, incrementId, document, safeExecute, eventHandler, addLeadingSlash } from '@tarojs/runtime';
|
|
3
3
|
|
|
4
|
-
const reactMeta = {
|
|
5
|
-
PageContext: EMPTY_OBJ,
|
|
6
|
-
R: EMPTY_OBJ
|
|
4
|
+
const reactMeta = {
|
|
5
|
+
PageContext: EMPTY_OBJ,
|
|
6
|
+
R: EMPTY_OBJ
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
-
const HOOKS_APP_ID = 'taro-app';
|
|
10
|
-
function isClassComponent(R, component) {
|
|
11
|
-
var _a;
|
|
12
|
-
const prototype = component.prototype;
|
|
13
|
-
// For React Redux
|
|
14
|
-
if ((_a = component.displayName) === null || _a === void 0 ? void 0 : _a.includes('Connect'))
|
|
15
|
-
return false;
|
|
16
|
-
return (isFunction(component.render) ||
|
|
17
|
-
!!(prototype === null || prototype === void 0 ? void 0 : prototype.isReactComponent) ||
|
|
18
|
-
prototype instanceof R.Component // compat for some others react-like library
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
function ensureIsArray(item) {
|
|
22
|
-
if (isArray(item)) {
|
|
23
|
-
return item;
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
return item ? [item] : [];
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* set writable, enumerable to true
|
|
31
|
-
*/
|
|
32
|
-
function setDefaultDescriptor(obj) {
|
|
33
|
-
obj.writable = true;
|
|
34
|
-
obj.enumerable = true;
|
|
35
|
-
return obj;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* 设置入口的路由参数
|
|
39
|
-
* @param options 小程序传入的参数
|
|
40
|
-
*/
|
|
41
|
-
function setRouterParams(options) {
|
|
42
|
-
Current.router = Object.assign({ params: options === null || options === void 0 ? void 0 : options.query }, options);
|
|
9
|
+
const HOOKS_APP_ID = 'taro-app';
|
|
10
|
+
function isClassComponent(R, component) {
|
|
11
|
+
var _a;
|
|
12
|
+
const prototype = component.prototype;
|
|
13
|
+
// For React Redux
|
|
14
|
+
if ((_a = component.displayName) === null || _a === void 0 ? void 0 : _a.includes('Connect'))
|
|
15
|
+
return false;
|
|
16
|
+
return (isFunction(component.render) ||
|
|
17
|
+
!!(prototype === null || prototype === void 0 ? void 0 : prototype.isReactComponent) ||
|
|
18
|
+
prototype instanceof R.Component // compat for some others react-like library
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
function ensureIsArray(item) {
|
|
22
|
+
if (isArray(item)) {
|
|
23
|
+
return item;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
return item ? [item] : [];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* set writable, enumerable to true
|
|
31
|
+
*/
|
|
32
|
+
function setDefaultDescriptor(obj) {
|
|
33
|
+
obj.writable = true;
|
|
34
|
+
obj.enumerable = true;
|
|
35
|
+
return obj;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 设置入口的路由参数
|
|
39
|
+
* @param options 小程序传入的参数
|
|
40
|
+
*/
|
|
41
|
+
function setRouterParams(options) {
|
|
42
|
+
Current.router = Object.assign({ params: options === null || options === void 0 ? void 0 : options.query }, options);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
const taroHooks = (lifecycle) => {
|
|
46
|
-
return (fn) => {
|
|
47
|
-
const { R: React, PageContext } = reactMeta;
|
|
48
|
-
const id = React.useContext(PageContext) || HOOKS_APP_ID;
|
|
49
|
-
// hold fn ref and keep up to date
|
|
50
|
-
const fnRef = React.useRef(fn);
|
|
51
|
-
if (fnRef.current !== fn)
|
|
52
|
-
fnRef.current = fn;
|
|
53
|
-
React.useLayoutEffect(() => {
|
|
54
|
-
let inst = getPageInstance(id);
|
|
55
|
-
let first = false;
|
|
56
|
-
if (inst == null) {
|
|
57
|
-
first = true;
|
|
58
|
-
inst = Object.create(null);
|
|
59
|
-
}
|
|
60
|
-
inst = inst;
|
|
61
|
-
// callback is immutable but inner function is up to date
|
|
62
|
-
const callback = (...args) => fnRef.current(...args);
|
|
63
|
-
if (isFunction(inst[lifecycle])) {
|
|
64
|
-
inst[lifecycle] = [inst[lifecycle], callback];
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
inst[lifecycle] = [
|
|
68
|
-
...(inst[lifecycle] || []),
|
|
69
|
-
callback
|
|
70
|
-
];
|
|
71
|
-
}
|
|
72
|
-
if (first) {
|
|
73
|
-
injectPageInstance(inst, id);
|
|
74
|
-
}
|
|
75
|
-
return () => {
|
|
76
|
-
const inst = getPageInstance(id);
|
|
77
|
-
const list = inst[lifecycle];
|
|
78
|
-
if (list === callback) {
|
|
79
|
-
inst[lifecycle] = undefined;
|
|
80
|
-
}
|
|
81
|
-
else if (isArray(list)) {
|
|
82
|
-
inst[lifecycle] = list.filter(item => item !== callback);
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
}, []);
|
|
86
|
-
};
|
|
87
|
-
};
|
|
88
|
-
const useDidShow = taroHooks('componentDidShow');
|
|
89
|
-
const useDidHide = taroHooks('componentDidHide');
|
|
90
|
-
const usePullDownRefresh = taroHooks('onPullDownRefresh');
|
|
91
|
-
const useReachBottom = taroHooks('onReachBottom');
|
|
92
|
-
const usePageScroll = taroHooks('onPageScroll');
|
|
93
|
-
const useResize = taroHooks('onResize');
|
|
94
|
-
const useShareAppMessage = taroHooks('onShareAppMessage');
|
|
95
|
-
const useTabItemTap = taroHooks('onTabItemTap');
|
|
96
|
-
const useTitleClick = taroHooks('onTitleClick');
|
|
97
|
-
const useOptionMenuClick = taroHooks('onOptionMenuClick');
|
|
98
|
-
const usePullIntercept = taroHooks('onPullIntercept');
|
|
99
|
-
const useShareTimeline = taroHooks('onShareTimeline');
|
|
100
|
-
const useAddToFavorites = taroHooks('onAddToFavorites');
|
|
101
|
-
const useSaveExitState = taroHooks('onSaveExitState');
|
|
102
|
-
const useReady = taroHooks('onReady');
|
|
103
|
-
const useLaunch = taroHooks('onLaunch');
|
|
104
|
-
const useLoad = taroHooks('onLoad');
|
|
105
|
-
const useUnload = taroHooks('onUnload');
|
|
106
|
-
const useError = taroHooks('onError');
|
|
107
|
-
const usePageNotFound = taroHooks('onPageNotFound');
|
|
108
|
-
const useRouter = (dynamic = false) => {
|
|
109
|
-
const React = reactMeta.R;
|
|
110
|
-
return dynamic ? Current.router : React.useMemo(() => Current.router, []);
|
|
111
|
-
};
|
|
45
|
+
const taroHooks = (lifecycle) => {
|
|
46
|
+
return (fn) => {
|
|
47
|
+
const { R: React, PageContext } = reactMeta;
|
|
48
|
+
const id = React.useContext(PageContext) || HOOKS_APP_ID;
|
|
49
|
+
// hold fn ref and keep up to date
|
|
50
|
+
const fnRef = React.useRef(fn);
|
|
51
|
+
if (fnRef.current !== fn)
|
|
52
|
+
fnRef.current = fn;
|
|
53
|
+
React.useLayoutEffect(() => {
|
|
54
|
+
let inst = getPageInstance(id);
|
|
55
|
+
let first = false;
|
|
56
|
+
if (inst == null) {
|
|
57
|
+
first = true;
|
|
58
|
+
inst = Object.create(null);
|
|
59
|
+
}
|
|
60
|
+
inst = inst;
|
|
61
|
+
// callback is immutable but inner function is up to date
|
|
62
|
+
const callback = (...args) => fnRef.current(...args);
|
|
63
|
+
if (isFunction(inst[lifecycle])) {
|
|
64
|
+
inst[lifecycle] = [inst[lifecycle], callback];
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
inst[lifecycle] = [
|
|
68
|
+
...(inst[lifecycle] || []),
|
|
69
|
+
callback
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
if (first) {
|
|
73
|
+
injectPageInstance(inst, id);
|
|
74
|
+
}
|
|
75
|
+
return () => {
|
|
76
|
+
const inst = getPageInstance(id);
|
|
77
|
+
const list = inst[lifecycle];
|
|
78
|
+
if (list === callback) {
|
|
79
|
+
inst[lifecycle] = undefined;
|
|
80
|
+
}
|
|
81
|
+
else if (isArray(list)) {
|
|
82
|
+
inst[lifecycle] = list.filter(item => item !== callback);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}, []);
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
const useDidShow = taroHooks('componentDidShow');
|
|
89
|
+
const useDidHide = taroHooks('componentDidHide');
|
|
90
|
+
const usePullDownRefresh = taroHooks('onPullDownRefresh');
|
|
91
|
+
const useReachBottom = taroHooks('onReachBottom');
|
|
92
|
+
const usePageScroll = taroHooks('onPageScroll');
|
|
93
|
+
const useResize = taroHooks('onResize');
|
|
94
|
+
const useShareAppMessage = taroHooks('onShareAppMessage');
|
|
95
|
+
const useTabItemTap = taroHooks('onTabItemTap');
|
|
96
|
+
const useTitleClick = taroHooks('onTitleClick');
|
|
97
|
+
const useOptionMenuClick = taroHooks('onOptionMenuClick');
|
|
98
|
+
const usePullIntercept = taroHooks('onPullIntercept');
|
|
99
|
+
const useShareTimeline = taroHooks('onShareTimeline');
|
|
100
|
+
const useAddToFavorites = taroHooks('onAddToFavorites');
|
|
101
|
+
const useSaveExitState = taroHooks('onSaveExitState');
|
|
102
|
+
const useReady = taroHooks('onReady');
|
|
103
|
+
const useLaunch = taroHooks('onLaunch');
|
|
104
|
+
const useLoad = taroHooks('onLoad');
|
|
105
|
+
const useUnload = taroHooks('onUnload');
|
|
106
|
+
const useError = taroHooks('onError');
|
|
107
|
+
const usePageNotFound = taroHooks('onPageNotFound');
|
|
108
|
+
const useRouter = (dynamic = false) => {
|
|
109
|
+
const React = reactMeta.R;
|
|
110
|
+
return dynamic ? Current.router : React.useMemo(() => Current.router, []);
|
|
111
|
+
};
|
|
112
112
|
const useScope = () => undefined;
|
|
113
113
|
|
|
114
114
|
var taroHooks$1 = /*#__PURE__*/Object.freeze({
|
|
@@ -137,532 +137,526 @@ var taroHooks$1 = /*#__PURE__*/Object.freeze({
|
|
|
137
137
|
useScope: useScope
|
|
138
138
|
});
|
|
139
139
|
|
|
140
|
-
let h$1;
|
|
141
|
-
let ReactDOM$1;
|
|
142
|
-
let Fragment;
|
|
143
|
-
const pageKeyId = incrementId();
|
|
144
|
-
function setReconciler(ReactDOM) {
|
|
145
|
-
hooks.tap('getLifecycle', function (instance, lifecycle) {
|
|
146
|
-
lifecycle = lifecycle.replace(/^on(Show|Hide)$/, 'componentDid$1');
|
|
147
|
-
return instance[lifecycle];
|
|
148
|
-
});
|
|
149
|
-
hooks.tap('modifyMpEvent', function (event) {
|
|
150
|
-
event.type = event.type.replace(/-/g, '');
|
|
151
|
-
});
|
|
152
|
-
hooks.tap('batchedEventUpdates', function (cb) {
|
|
153
|
-
ReactDOM.unstable_batchedUpdates(cb);
|
|
154
|
-
});
|
|
155
|
-
hooks.tap('mergePageInstance', function (prev, next) {
|
|
156
|
-
if (!prev || !next)
|
|
157
|
-
return;
|
|
158
|
-
// 子组件使用 lifecycle hooks 注册了生命周期后,会存在 prev,里面是注册的生命周期回调。
|
|
159
|
-
// prev 使用 Object.create(null) 创建,H5 的 fast-refresh 可能也会导致存在 prev,要排除这些意外产生的 prev
|
|
160
|
-
if ('constructor' in prev)
|
|
161
|
-
return;
|
|
162
|
-
Object.keys(prev).forEach(item => {
|
|
163
|
-
const prevList = prev[item];
|
|
164
|
-
const nextList = ensureIsArray(next[item]);
|
|
165
|
-
next[item] = nextList.concat(prevList);
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
if (process.env.TARO_ENV === 'h5') {
|
|
169
|
-
hooks.tap('createPullDownComponent', (el, _, R, customWrapper) => {
|
|
170
|
-
const isReactComponent = isClassComponent(R, el);
|
|
171
|
-
return R.forwardRef((props, ref) => {
|
|
172
|
-
const newProps = Object.assign({}, props);
|
|
173
|
-
const refs = isReactComponent ? { ref: ref } : {
|
|
174
|
-
forwardedRef: ref,
|
|
175
|
-
// 兼容 react-redux 7.20.1+
|
|
176
|
-
reactReduxForwardedRef: ref
|
|
177
|
-
};
|
|
178
|
-
return h$1(customWrapper || 'taro-pull-to-refresh', null, h$1(el, Object.assign(Object.assign({}, newProps), refs)));
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
hooks.tap('getDOMNode', inst => {
|
|
182
|
-
return ReactDOM.findDOMNode(inst);
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
function connectReactPage(R, id) {
|
|
187
|
-
return (Page) => {
|
|
188
|
-
// eslint-disable-next-line dot-notation
|
|
189
|
-
const isReactComponent = isClassComponent(R, Page);
|
|
190
|
-
const inject = (node) => node && injectPageInstance(node, id);
|
|
191
|
-
const refs = isReactComponent ? { ref: inject } : {
|
|
192
|
-
forwardedRef: inject,
|
|
193
|
-
// 兼容 react-redux 7.20.1+
|
|
194
|
-
reactReduxForwardedRef: inject
|
|
195
|
-
};
|
|
196
|
-
if (reactMeta.PageContext === EMPTY_OBJ) {
|
|
197
|
-
reactMeta.PageContext = R.createContext('');
|
|
198
|
-
}
|
|
199
|
-
return class PageWrapper extends R.Component {
|
|
200
|
-
constructor() {
|
|
201
|
-
super(...arguments);
|
|
202
|
-
this.state = {
|
|
203
|
-
hasError: false
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
static getDerivedStateFromError(error) {
|
|
207
|
-
var _a, _b;
|
|
208
|
-
(_b = (_a = Current.app) === null || _a === void 0 ? void 0 : _a.onError) === null || _b === void 0 ? void 0 : _b.call(_a, error.message + error.stack);
|
|
209
|
-
return { hasError: true };
|
|
210
|
-
}
|
|
211
|
-
// React 16 uncaught error 会导致整个应用 crash,
|
|
212
|
-
// 目前把错误缩小到页面
|
|
213
|
-
componentDidCatch(error, info) {
|
|
214
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
215
|
-
console.warn(error);
|
|
216
|
-
console.error(info.componentStack);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
render() {
|
|
220
|
-
const children = this.state.hasError
|
|
221
|
-
? []
|
|
222
|
-
: h$1(reactMeta.PageContext.Provider, { value: id }, h$1(Page, Object.assign(Object.assign({}, this.props), refs)));
|
|
223
|
-
if (process.env.TARO_ENV === 'h5') {
|
|
224
|
-
return h$1('div', { id, className: 'taro_page' }, children);
|
|
225
|
-
}
|
|
226
|
-
else {
|
|
227
|
-
return h$1('root', { id }, children);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
};
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* 桥接小程序 App 构造器和 React 渲染流程
|
|
235
|
-
* @param App 用户编写的入口组件
|
|
236
|
-
* @param react 框架
|
|
237
|
-
* @param dom 框架渲染器
|
|
238
|
-
* @param config 入口组件配置 app.config.js 的内容
|
|
239
|
-
* @returns 传递给 App 构造器的对象 obj :App(obj)
|
|
240
|
-
*/
|
|
241
|
-
function createReactApp(App, react, dom, config) {
|
|
242
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
243
|
-
ensure(!!dom, '构建 React/Nerv 项目请把 process.env.FRAMEWORK 设置为 \'react\'/\'nerv\' ');
|
|
244
|
-
}
|
|
245
|
-
reactMeta.R = react;
|
|
246
|
-
h$1 = react.createElement;
|
|
247
|
-
ReactDOM$1 = dom;
|
|
248
|
-
Fragment = react.Fragment;
|
|
249
|
-
const appInstanceRef = react.createRef();
|
|
250
|
-
const isReactComponent = isClassComponent(react, App);
|
|
251
|
-
let appWrapper;
|
|
252
|
-
setReconciler(ReactDOM$1);
|
|
253
|
-
function getAppInstance() {
|
|
254
|
-
return appInstanceRef.current;
|
|
255
|
-
}
|
|
256
|
-
function renderReactRoot() {
|
|
257
|
-
var _a, _b;
|
|
258
|
-
const reactMode = __TARO_FRAMEWORK_REACT_MODE__;
|
|
259
|
-
let appId = 'app';
|
|
260
|
-
if (process.env.TARO_ENV === 'h5') {
|
|
261
|
-
appId = (config === null || config === void 0 ? void 0 : config.appId) || appId;
|
|
262
|
-
}
|
|
263
|
-
else {
|
|
264
|
-
ReactDOM$1.version = react.version;
|
|
265
|
-
}
|
|
266
|
-
const container = document.getElementById(appId);
|
|
267
|
-
const version = Number((ReactDOM$1.version || '').split('.')[0]);
|
|
268
|
-
if (version >= 18 && reactMode === 'concurrent') {
|
|
269
|
-
const root = ReactDOM$1.createRoot(container);
|
|
270
|
-
(_a = root.render) === null || _a === void 0 ? void 0 : _a.call(root, h$1(AppWrapper));
|
|
271
|
-
}
|
|
272
|
-
else {
|
|
273
|
-
(_b = ReactDOM$1.render) === null || _b === void 0 ? void 0 : _b.call(ReactDOM$1, h$1(AppWrapper), container);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
class AppWrapper extends react.Component {
|
|
277
|
-
constructor(props) {
|
|
278
|
-
super(props);
|
|
279
|
-
// run createElement() inside the render function to make sure that owner is right
|
|
280
|
-
this.pages = [];
|
|
281
|
-
this.elements = [];
|
|
282
|
-
appWrapper = this;
|
|
283
|
-
}
|
|
284
|
-
mount(pageComponent, id, cb) {
|
|
285
|
-
const pageWrapper = connectReactPage(react, id)(pageComponent);
|
|
286
|
-
const key = id + pageKeyId();
|
|
287
|
-
const page = () => h$1(pageWrapper, { key, tid: id });
|
|
288
|
-
this.pages.push(page);
|
|
289
|
-
this.forceUpdate(cb);
|
|
290
|
-
}
|
|
291
|
-
unmount(id, cb) {
|
|
292
|
-
const elements = this.elements;
|
|
293
|
-
const idx = elements.findIndex(item => item.props.tid === id);
|
|
294
|
-
elements.splice(idx, 1);
|
|
295
|
-
this.forceUpdate(cb);
|
|
296
|
-
}
|
|
297
|
-
render() {
|
|
298
|
-
const { pages, elements } = this;
|
|
299
|
-
while (pages.length > 0) {
|
|
300
|
-
const page = pages.pop();
|
|
301
|
-
elements.push(page());
|
|
302
|
-
}
|
|
303
|
-
let props = null;
|
|
304
|
-
if (isReactComponent) {
|
|
305
|
-
props = { ref: appInstanceRef };
|
|
306
|
-
}
|
|
307
|
-
return h$1(App, props, process.env.TARO_ENV === 'h5' ? h$1(Fragment !== null && Fragment !== void 0 ? Fragment : 'div', null, elements.slice()) : elements.slice());
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
if (process.env.TARO_ENV !== 'h5') {
|
|
311
|
-
renderReactRoot();
|
|
312
|
-
}
|
|
313
|
-
const [ONLAUNCH, ONSHOW, ONHIDE] = hooks.call('getMiniLifecycleImpl').app;
|
|
314
|
-
const appObj = Object.create({
|
|
315
|
-
render(cb) {
|
|
316
|
-
appWrapper.forceUpdate(cb);
|
|
317
|
-
},
|
|
318
|
-
mount(component, id, cb) {
|
|
319
|
-
appWrapper.mount(component, id, cb);
|
|
320
|
-
},
|
|
321
|
-
unmount(id, cb) {
|
|
322
|
-
appWrapper.unmount(id, cb);
|
|
323
|
-
}
|
|
324
|
-
}, {
|
|
325
|
-
config: setDefaultDescriptor({
|
|
326
|
-
configurable: true,
|
|
327
|
-
value: config
|
|
328
|
-
}),
|
|
329
|
-
[ONLAUNCH]: setDefaultDescriptor({
|
|
330
|
-
value(options) {
|
|
331
|
-
var _a;
|
|
332
|
-
setRouterParams(options);
|
|
333
|
-
if (process.env.TARO_ENV === 'h5') {
|
|
334
|
-
// 由于 H5 路由初始化的时候会清除 app 下的 dom 元素,所以需要在路由初始化后执行 render
|
|
335
|
-
renderReactRoot();
|
|
336
|
-
}
|
|
337
|
-
// 用户编写的入口组件实例
|
|
338
|
-
const app = getAppInstance();
|
|
339
|
-
this.$app = app;
|
|
340
|
-
if (app) {
|
|
341
|
-
// 把 App Class 上挂载的额外属性同步到全局 app 对象中
|
|
342
|
-
if (app.taroGlobalData) {
|
|
343
|
-
const globalData = app.taroGlobalData;
|
|
344
|
-
const keys = Object.keys(globalData);
|
|
345
|
-
const descriptors = Object.getOwnPropertyDescriptors(globalData);
|
|
346
|
-
keys.forEach(key => {
|
|
347
|
-
Object.defineProperty(this, key, {
|
|
348
|
-
configurable: true,
|
|
349
|
-
enumerable: true,
|
|
350
|
-
get() {
|
|
351
|
-
return globalData[key];
|
|
352
|
-
},
|
|
353
|
-
set(value) {
|
|
354
|
-
globalData[key] = value;
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
});
|
|
358
|
-
Object.defineProperties(this, descriptors);
|
|
359
|
-
}
|
|
360
|
-
(_a = app.onLaunch) === null || _a === void 0 ? void 0 : _a.call(app, options);
|
|
361
|
-
}
|
|
362
|
-
triggerAppHook('onLaunch', options);
|
|
363
|
-
}
|
|
364
|
-
}),
|
|
365
|
-
[ONSHOW]: setDefaultDescriptor({
|
|
366
|
-
value(options) {
|
|
367
|
-
var _a;
|
|
368
|
-
setRouterParams(options);
|
|
369
|
-
/**
|
|
370
|
-
* trigger lifecycle
|
|
371
|
-
*/
|
|
372
|
-
const app = getAppInstance();
|
|
373
|
-
// class component, componentDidShow
|
|
374
|
-
(_a = app === null || app === void 0 ? void 0 : app.componentDidShow) === null || _a === void 0 ? void 0 : _a.call(app, options);
|
|
375
|
-
// functional component, useDidShow
|
|
376
|
-
triggerAppHook('onShow', options);
|
|
377
|
-
}
|
|
378
|
-
}),
|
|
379
|
-
[ONHIDE]: setDefaultDescriptor({
|
|
380
|
-
value() {
|
|
381
|
-
var _a;
|
|
382
|
-
/**
|
|
383
|
-
* trigger lifecycle
|
|
384
|
-
*/
|
|
385
|
-
const app = getAppInstance();
|
|
386
|
-
// class component, componentDidHide
|
|
387
|
-
(_a = app === null || app === void 0 ? void 0 : app.componentDidHide) === null || _a === void 0 ? void 0 : _a.call(app);
|
|
388
|
-
// functional component, useDidHide
|
|
389
|
-
triggerAppHook('onHide');
|
|
390
|
-
}
|
|
391
|
-
}),
|
|
392
|
-
onError: setDefaultDescriptor({
|
|
393
|
-
value(error) {
|
|
394
|
-
var _a;
|
|
395
|
-
const app = getAppInstance();
|
|
396
|
-
(_a = app === null || app === void 0 ? void 0 : app.onError) === null || _a === void 0 ? void 0 : _a.call(app, error);
|
|
397
|
-
triggerAppHook('onError', error);
|
|
398
|
-
if (process.env.NODE_ENV !== 'production' && error.includes('Minified React error')) {
|
|
399
|
-
console.warn('React 出现报错,请打开编译配置 mini.debugReact 查看报错详情:https://docs.taro.zone/docs/config-detail#minidebugreact');
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
}),
|
|
403
|
-
onPageNotFound: setDefaultDescriptor({
|
|
404
|
-
value(res) {
|
|
405
|
-
var _a;
|
|
406
|
-
const app = getAppInstance();
|
|
407
|
-
(_a = app === null || app === void 0 ? void 0 : app.onPageNotFound) === null || _a === void 0 ? void 0 : _a.call(app, res);
|
|
408
|
-
triggerAppHook('onPageNotFound', res);
|
|
409
|
-
}
|
|
410
|
-
})
|
|
411
|
-
});
|
|
412
|
-
function triggerAppHook(lifecycle, ...option) {
|
|
413
|
-
const instance = getPageInstance(HOOKS_APP_ID);
|
|
414
|
-
if (instance) {
|
|
415
|
-
const app = getAppInstance();
|
|
416
|
-
const func = hooks.call('getLifecycle', instance, lifecycle);
|
|
417
|
-
if (Array.isArray(func)) {
|
|
418
|
-
func.forEach(cb => cb.apply(app, option));
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
Current.app = appObj;
|
|
423
|
-
return appObj;
|
|
140
|
+
let h$1;
|
|
141
|
+
let ReactDOM$1;
|
|
142
|
+
let Fragment;
|
|
143
|
+
const pageKeyId = incrementId();
|
|
144
|
+
function setReconciler(ReactDOM) {
|
|
145
|
+
hooks.tap('getLifecycle', function (instance, lifecycle) {
|
|
146
|
+
lifecycle = lifecycle.replace(/^on(Show|Hide)$/, 'componentDid$1');
|
|
147
|
+
return instance[lifecycle];
|
|
148
|
+
});
|
|
149
|
+
hooks.tap('modifyMpEvent', function (event) {
|
|
150
|
+
event.type = event.type.replace(/-/g, '');
|
|
151
|
+
});
|
|
152
|
+
hooks.tap('batchedEventUpdates', function (cb) {
|
|
153
|
+
ReactDOM.unstable_batchedUpdates(cb);
|
|
154
|
+
});
|
|
155
|
+
hooks.tap('mergePageInstance', function (prev, next) {
|
|
156
|
+
if (!prev || !next)
|
|
157
|
+
return;
|
|
158
|
+
// 子组件使用 lifecycle hooks 注册了生命周期后,会存在 prev,里面是注册的生命周期回调。
|
|
159
|
+
// prev 使用 Object.create(null) 创建,H5 的 fast-refresh 可能也会导致存在 prev,要排除这些意外产生的 prev
|
|
160
|
+
if ('constructor' in prev)
|
|
161
|
+
return;
|
|
162
|
+
Object.keys(prev).forEach(item => {
|
|
163
|
+
const prevList = prev[item];
|
|
164
|
+
const nextList = ensureIsArray(next[item]);
|
|
165
|
+
next[item] = nextList.concat(prevList);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
if (process.env.TARO_ENV === 'h5') {
|
|
169
|
+
hooks.tap('createPullDownComponent', (el, _, R, customWrapper) => {
|
|
170
|
+
const isReactComponent = isClassComponent(R, el);
|
|
171
|
+
return R.forwardRef((props, ref) => {
|
|
172
|
+
const newProps = Object.assign({}, props);
|
|
173
|
+
const refs = isReactComponent ? { ref: ref } : {
|
|
174
|
+
forwardedRef: ref,
|
|
175
|
+
// 兼容 react-redux 7.20.1+
|
|
176
|
+
reactReduxForwardedRef: ref
|
|
177
|
+
};
|
|
178
|
+
return h$1(customWrapper || 'taro-pull-to-refresh', null, h$1(el, Object.assign(Object.assign({}, newProps), refs)));
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
hooks.tap('getDOMNode', inst => {
|
|
182
|
+
return ReactDOM.findDOMNode(inst);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function connectReactPage(R, id) {
|
|
187
|
+
return (Page) => {
|
|
188
|
+
// eslint-disable-next-line dot-notation
|
|
189
|
+
const isReactComponent = isClassComponent(R, Page);
|
|
190
|
+
const inject = (node) => node && injectPageInstance(node, id);
|
|
191
|
+
const refs = isReactComponent ? { ref: inject } : {
|
|
192
|
+
forwardedRef: inject,
|
|
193
|
+
// 兼容 react-redux 7.20.1+
|
|
194
|
+
reactReduxForwardedRef: inject
|
|
195
|
+
};
|
|
196
|
+
if (reactMeta.PageContext === EMPTY_OBJ) {
|
|
197
|
+
reactMeta.PageContext = R.createContext('');
|
|
198
|
+
}
|
|
199
|
+
return class PageWrapper extends R.Component {
|
|
200
|
+
constructor() {
|
|
201
|
+
super(...arguments);
|
|
202
|
+
this.state = {
|
|
203
|
+
hasError: false
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
static getDerivedStateFromError(error) {
|
|
207
|
+
var _a, _b;
|
|
208
|
+
(_b = (_a = Current.app) === null || _a === void 0 ? void 0 : _a.onError) === null || _b === void 0 ? void 0 : _b.call(_a, error.message + error.stack);
|
|
209
|
+
return { hasError: true };
|
|
210
|
+
}
|
|
211
|
+
// React 16 uncaught error 会导致整个应用 crash,
|
|
212
|
+
// 目前把错误缩小到页面
|
|
213
|
+
componentDidCatch(error, info) {
|
|
214
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
215
|
+
console.warn(error);
|
|
216
|
+
console.error(info.componentStack);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
render() {
|
|
220
|
+
const children = this.state.hasError
|
|
221
|
+
? []
|
|
222
|
+
: h$1(reactMeta.PageContext.Provider, { value: id }, h$1(Page, Object.assign(Object.assign({}, this.props), refs)));
|
|
223
|
+
if (process.env.TARO_ENV === 'h5') {
|
|
224
|
+
return h$1('div', { id, className: 'taro_page' }, children);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
return h$1('root', { id }, children);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* 桥接小程序 App 构造器和 React 渲染流程
|
|
235
|
+
* @param App 用户编写的入口组件
|
|
236
|
+
* @param react 框架
|
|
237
|
+
* @param dom 框架渲染器
|
|
238
|
+
* @param config 入口组件配置 app.config.js 的内容
|
|
239
|
+
* @returns 传递给 App 构造器的对象 obj :App(obj)
|
|
240
|
+
*/
|
|
241
|
+
function createReactApp(App, react, dom, config) {
|
|
242
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
243
|
+
ensure(!!dom, '构建 React/Nerv 项目请把 process.env.FRAMEWORK 设置为 \'react\'/\'nerv\' ');
|
|
244
|
+
}
|
|
245
|
+
reactMeta.R = react;
|
|
246
|
+
h$1 = react.createElement;
|
|
247
|
+
ReactDOM$1 = dom;
|
|
248
|
+
Fragment = react.Fragment;
|
|
249
|
+
const appInstanceRef = react.createRef();
|
|
250
|
+
const isReactComponent = isClassComponent(react, App);
|
|
251
|
+
let appWrapper;
|
|
252
|
+
setReconciler(ReactDOM$1);
|
|
253
|
+
function getAppInstance() {
|
|
254
|
+
return appInstanceRef.current;
|
|
255
|
+
}
|
|
256
|
+
function renderReactRoot() {
|
|
257
|
+
var _a, _b;
|
|
258
|
+
const reactMode = __TARO_FRAMEWORK_REACT_MODE__;
|
|
259
|
+
let appId = 'app';
|
|
260
|
+
if (process.env.TARO_ENV === 'h5') {
|
|
261
|
+
appId = (config === null || config === void 0 ? void 0 : config.appId) || appId;
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
ReactDOM$1.version = react.version;
|
|
265
|
+
}
|
|
266
|
+
const container = document.getElementById(appId);
|
|
267
|
+
const version = Number((ReactDOM$1.version || '').split('.')[0]);
|
|
268
|
+
if (version >= 18 && reactMode === 'concurrent') {
|
|
269
|
+
const root = ReactDOM$1.createRoot(container);
|
|
270
|
+
(_a = root.render) === null || _a === void 0 ? void 0 : _a.call(root, h$1(AppWrapper));
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
(_b = ReactDOM$1.render) === null || _b === void 0 ? void 0 : _b.call(ReactDOM$1, h$1(AppWrapper), container);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
class AppWrapper extends react.Component {
|
|
277
|
+
constructor(props) {
|
|
278
|
+
super(props);
|
|
279
|
+
// run createElement() inside the render function to make sure that owner is right
|
|
280
|
+
this.pages = [];
|
|
281
|
+
this.elements = [];
|
|
282
|
+
appWrapper = this;
|
|
283
|
+
}
|
|
284
|
+
mount(pageComponent, id, cb) {
|
|
285
|
+
const pageWrapper = connectReactPage(react, id)(pageComponent);
|
|
286
|
+
const key = id + pageKeyId();
|
|
287
|
+
const page = () => h$1(pageWrapper, { key, tid: id });
|
|
288
|
+
this.pages.push(page);
|
|
289
|
+
this.forceUpdate(cb);
|
|
290
|
+
}
|
|
291
|
+
unmount(id, cb) {
|
|
292
|
+
const elements = this.elements;
|
|
293
|
+
const idx = elements.findIndex(item => item.props.tid === id);
|
|
294
|
+
elements.splice(idx, 1);
|
|
295
|
+
this.forceUpdate(cb);
|
|
296
|
+
}
|
|
297
|
+
render() {
|
|
298
|
+
const { pages, elements } = this;
|
|
299
|
+
while (pages.length > 0) {
|
|
300
|
+
const page = pages.pop();
|
|
301
|
+
elements.push(page());
|
|
302
|
+
}
|
|
303
|
+
let props = null;
|
|
304
|
+
if (isReactComponent) {
|
|
305
|
+
props = { ref: appInstanceRef };
|
|
306
|
+
}
|
|
307
|
+
return h$1(App, props, process.env.TARO_ENV === 'h5' ? h$1(Fragment !== null && Fragment !== void 0 ? Fragment : 'div', null, elements.slice()) : elements.slice());
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
if (process.env.TARO_ENV !== 'h5') {
|
|
311
|
+
renderReactRoot();
|
|
312
|
+
}
|
|
313
|
+
const [ONLAUNCH, ONSHOW, ONHIDE] = hooks.call('getMiniLifecycleImpl').app;
|
|
314
|
+
const appObj = Object.create({
|
|
315
|
+
render(cb) {
|
|
316
|
+
appWrapper.forceUpdate(cb);
|
|
317
|
+
},
|
|
318
|
+
mount(component, id, cb) {
|
|
319
|
+
appWrapper.mount(component, id, cb);
|
|
320
|
+
},
|
|
321
|
+
unmount(id, cb) {
|
|
322
|
+
appWrapper.unmount(id, cb);
|
|
323
|
+
}
|
|
324
|
+
}, {
|
|
325
|
+
config: setDefaultDescriptor({
|
|
326
|
+
configurable: true,
|
|
327
|
+
value: config
|
|
328
|
+
}),
|
|
329
|
+
[ONLAUNCH]: setDefaultDescriptor({
|
|
330
|
+
value(options) {
|
|
331
|
+
var _a;
|
|
332
|
+
setRouterParams(options);
|
|
333
|
+
if (process.env.TARO_ENV === 'h5') {
|
|
334
|
+
// 由于 H5 路由初始化的时候会清除 app 下的 dom 元素,所以需要在路由初始化后执行 render
|
|
335
|
+
renderReactRoot();
|
|
336
|
+
}
|
|
337
|
+
// 用户编写的入口组件实例
|
|
338
|
+
const app = getAppInstance();
|
|
339
|
+
this.$app = app;
|
|
340
|
+
if (app) {
|
|
341
|
+
// 把 App Class 上挂载的额外属性同步到全局 app 对象中
|
|
342
|
+
if (app.taroGlobalData) {
|
|
343
|
+
const globalData = app.taroGlobalData;
|
|
344
|
+
const keys = Object.keys(globalData);
|
|
345
|
+
const descriptors = Object.getOwnPropertyDescriptors(globalData);
|
|
346
|
+
keys.forEach(key => {
|
|
347
|
+
Object.defineProperty(this, key, {
|
|
348
|
+
configurable: true,
|
|
349
|
+
enumerable: true,
|
|
350
|
+
get() {
|
|
351
|
+
return globalData[key];
|
|
352
|
+
},
|
|
353
|
+
set(value) {
|
|
354
|
+
globalData[key] = value;
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
Object.defineProperties(this, descriptors);
|
|
359
|
+
}
|
|
360
|
+
(_a = app.onLaunch) === null || _a === void 0 ? void 0 : _a.call(app, options);
|
|
361
|
+
}
|
|
362
|
+
triggerAppHook('onLaunch', options);
|
|
363
|
+
}
|
|
364
|
+
}),
|
|
365
|
+
[ONSHOW]: setDefaultDescriptor({
|
|
366
|
+
value(options) {
|
|
367
|
+
var _a;
|
|
368
|
+
setRouterParams(options);
|
|
369
|
+
/**
|
|
370
|
+
* trigger lifecycle
|
|
371
|
+
*/
|
|
372
|
+
const app = getAppInstance();
|
|
373
|
+
// class component, componentDidShow
|
|
374
|
+
(_a = app === null || app === void 0 ? void 0 : app.componentDidShow) === null || _a === void 0 ? void 0 : _a.call(app, options);
|
|
375
|
+
// functional component, useDidShow
|
|
376
|
+
triggerAppHook('onShow', options);
|
|
377
|
+
}
|
|
378
|
+
}),
|
|
379
|
+
[ONHIDE]: setDefaultDescriptor({
|
|
380
|
+
value() {
|
|
381
|
+
var _a;
|
|
382
|
+
/**
|
|
383
|
+
* trigger lifecycle
|
|
384
|
+
*/
|
|
385
|
+
const app = getAppInstance();
|
|
386
|
+
// class component, componentDidHide
|
|
387
|
+
(_a = app === null || app === void 0 ? void 0 : app.componentDidHide) === null || _a === void 0 ? void 0 : _a.call(app);
|
|
388
|
+
// functional component, useDidHide
|
|
389
|
+
triggerAppHook('onHide');
|
|
390
|
+
}
|
|
391
|
+
}),
|
|
392
|
+
onError: setDefaultDescriptor({
|
|
393
|
+
value(error) {
|
|
394
|
+
var _a;
|
|
395
|
+
const app = getAppInstance();
|
|
396
|
+
(_a = app === null || app === void 0 ? void 0 : app.onError) === null || _a === void 0 ? void 0 : _a.call(app, error);
|
|
397
|
+
triggerAppHook('onError', error);
|
|
398
|
+
if (process.env.NODE_ENV !== 'production' && error.includes('Minified React error')) {
|
|
399
|
+
console.warn('React 出现报错,请打开编译配置 mini.debugReact 查看报错详情:https://docs.taro.zone/docs/config-detail#minidebugreact');
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}),
|
|
403
|
+
onPageNotFound: setDefaultDescriptor({
|
|
404
|
+
value(res) {
|
|
405
|
+
var _a;
|
|
406
|
+
const app = getAppInstance();
|
|
407
|
+
(_a = app === null || app === void 0 ? void 0 : app.onPageNotFound) === null || _a === void 0 ? void 0 : _a.call(app, res);
|
|
408
|
+
triggerAppHook('onPageNotFound', res);
|
|
409
|
+
}
|
|
410
|
+
})
|
|
411
|
+
});
|
|
412
|
+
function triggerAppHook(lifecycle, ...option) {
|
|
413
|
+
const instance = getPageInstance(HOOKS_APP_ID);
|
|
414
|
+
if (instance) {
|
|
415
|
+
const app = getAppInstance();
|
|
416
|
+
const func = hooks.call('getLifecycle', instance, lifecycle);
|
|
417
|
+
if (Array.isArray(func)) {
|
|
418
|
+
func.forEach(cb => cb.apply(app, option));
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
Current.app = appObj;
|
|
423
|
+
return appObj;
|
|
424
424
|
}
|
|
425
425
|
|
|
426
|
-
const getNativeCompId = incrementId();
|
|
427
|
-
let h;
|
|
428
|
-
let ReactDOM;
|
|
429
|
-
function initNativeComponentEntry(R, ReactDOM) {
|
|
430
|
-
class NativeComponentWrapper extends R.Component {
|
|
431
|
-
constructor() {
|
|
432
|
-
super(...arguments);
|
|
433
|
-
this.root = R.createRef();
|
|
434
|
-
this.ctx = this.props.getCtx();
|
|
435
|
-
}
|
|
436
|
-
componentDidMount() {
|
|
437
|
-
this.ctx.component = this;
|
|
438
|
-
const rootElement = this.root.current;
|
|
439
|
-
rootElement.ctx = this.ctx;
|
|
440
|
-
rootElement.performUpdate(true);
|
|
441
|
-
}
|
|
442
|
-
render() {
|
|
443
|
-
return (h('root', {
|
|
444
|
-
ref: this.root
|
|
445
|
-
}, this.props.renderComponent(this.ctx)));
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
class Entry extends R.Component {
|
|
449
|
-
constructor() {
|
|
450
|
-
super(...arguments);
|
|
451
|
-
this.state = {
|
|
452
|
-
components: []
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
componentDidMount() {
|
|
456
|
-
Current.app = this;
|
|
457
|
-
}
|
|
458
|
-
mount(Component, compId, getCtx) {
|
|
459
|
-
const isReactComponent = isClassComponent(R, Component);
|
|
460
|
-
const inject = (node) => node && injectPageInstance(node, compId);
|
|
461
|
-
const refs = isReactComponent ? { ref: inject } : {
|
|
462
|
-
forwardedRef: inject,
|
|
463
|
-
reactReduxForwardedRef: inject
|
|
464
|
-
};
|
|
465
|
-
if (reactMeta.PageContext === EMPTY_OBJ) {
|
|
466
|
-
reactMeta.PageContext = R.createContext('');
|
|
467
|
-
}
|
|
468
|
-
const item = {
|
|
469
|
-
compId,
|
|
470
|
-
element: h(NativeComponentWrapper, {
|
|
471
|
-
key: compId,
|
|
472
|
-
getCtx,
|
|
473
|
-
renderComponent(ctx) {
|
|
474
|
-
return h(reactMeta.PageContext.Provider, { value: compId }, h(Component, Object.assign(Object.assign(Object.assign({}, (ctx.data || (ctx.data = {})).props), refs), { $scope: ctx })));
|
|
475
|
-
}
|
|
476
|
-
})
|
|
477
|
-
};
|
|
478
|
-
this.setState({
|
|
479
|
-
components: [...this.state.components, item]
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
|
-
unmount(compId) {
|
|
483
|
-
const components = this.state.components;
|
|
484
|
-
const index = components.findIndex(item => item.compId === compId);
|
|
485
|
-
const next = [...components.slice(0, index), ...components.slice(index + 1)];
|
|
486
|
-
this.setState({
|
|
487
|
-
components: next
|
|
488
|
-
});
|
|
489
|
-
}
|
|
490
|
-
render() {
|
|
491
|
-
const components = this.state.components;
|
|
492
|
-
return (components.map(({ element }) => element));
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
setReconciler(ReactDOM);
|
|
496
|
-
const app = document.getElementById('app');
|
|
497
|
-
ReactDOM.render(h(Entry, {}), app);
|
|
498
|
-
}
|
|
499
|
-
function createNativeComponentConfig(Component, react, reactdom, componentConfig) {
|
|
500
|
-
var _a, _b;
|
|
501
|
-
reactMeta.R = react;
|
|
502
|
-
h = react.createElement;
|
|
503
|
-
ReactDOM = reactdom;
|
|
504
|
-
setReconciler(ReactDOM);
|
|
505
|
-
const componentObj = {
|
|
506
|
-
options: componentConfig,
|
|
507
|
-
properties: {
|
|
508
|
-
props: {
|
|
509
|
-
type: null,
|
|
510
|
-
value: null,
|
|
511
|
-
observer(_newVal, oldVal) {
|
|
512
|
-
oldVal && this.component.forceUpdate();
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
},
|
|
516
|
-
created() {
|
|
517
|
-
if (!Current.app) {
|
|
518
|
-
initNativeComponentEntry(react, ReactDOM);
|
|
519
|
-
}
|
|
520
|
-
},
|
|
521
|
-
attached() {
|
|
522
|
-
const compId = this.compId = getNativeCompId();
|
|
523
|
-
setCurrent(compId);
|
|
524
|
-
this.config = componentConfig;
|
|
525
|
-
Current.app.mount(Component, compId, () => this);
|
|
526
|
-
},
|
|
527
|
-
ready() {
|
|
528
|
-
safeExecute(this.compId, 'onReady');
|
|
529
|
-
},
|
|
530
|
-
detached() {
|
|
531
|
-
Current.app.unmount(this.compId);
|
|
532
|
-
},
|
|
533
|
-
pageLifetimes: {
|
|
534
|
-
show(options) {
|
|
535
|
-
safeExecute(this.compId, 'onShow', options);
|
|
536
|
-
},
|
|
537
|
-
hide() {
|
|
538
|
-
safeExecute(this.compId, 'onHide');
|
|
539
|
-
}
|
|
540
|
-
},
|
|
541
|
-
methods: {
|
|
542
|
-
eh: eventHandler
|
|
543
|
-
}
|
|
544
|
-
};
|
|
545
|
-
function setCurrent(compId) {
|
|
546
|
-
const pages = getCurrentPages();
|
|
547
|
-
const currentPage = pages[pages.length - 1];
|
|
548
|
-
if (Current.page === currentPage)
|
|
549
|
-
return;
|
|
550
|
-
Current.page = currentPage;
|
|
551
|
-
const route = currentPage.route || currentPage.__route__;
|
|
552
|
-
const router = {
|
|
553
|
-
params: currentPage.options || {},
|
|
554
|
-
path: addLeadingSlash(route),
|
|
555
|
-
$taroPath: compId,
|
|
556
|
-
onReady: '',
|
|
557
|
-
onHide: '',
|
|
558
|
-
onShow: ''
|
|
559
|
-
};
|
|
560
|
-
Current.router = router;
|
|
561
|
-
if (!currentPage.options) {
|
|
562
|
-
// 例如在微信小程序中,页面 options 的设置时机比组件 attached 慢
|
|
563
|
-
Object.defineProperty(currentPage, 'options', {
|
|
564
|
-
enumerable: true,
|
|
565
|
-
configurable: true,
|
|
566
|
-
get() {
|
|
567
|
-
return this._optionsValue;
|
|
568
|
-
},
|
|
569
|
-
set(value) {
|
|
570
|
-
router.params = value;
|
|
571
|
-
this._optionsValue = value;
|
|
572
|
-
}
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
// onShareAppMessage 和 onShareTimeline 一样,会影响小程序右上方按钮的选项,因此不能默认注册。
|
|
577
|
-
if (Component.onShareAppMessage ||
|
|
578
|
-
((_a = Component.prototype) === null || _a === void 0 ? void 0 : _a.onShareAppMessage) ||
|
|
579
|
-
Component.enableShareAppMessage) {
|
|
580
|
-
componentObj.methods.onShareAppMessage = function (options) {
|
|
581
|
-
const target = options === null || options === void 0 ? void 0 : options.target;
|
|
582
|
-
if (target) {
|
|
583
|
-
const id = target.id;
|
|
584
|
-
const element = document.getElementById(id);
|
|
585
|
-
if (element) {
|
|
586
|
-
target.dataset = element.dataset;
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
return safeExecute(this.compId, 'onShareAppMessage', options);
|
|
590
|
-
};
|
|
591
|
-
}
|
|
592
|
-
if (Component.onShareTimeline ||
|
|
593
|
-
((_b = Component.prototype) === null || _b === void 0 ? void 0 : _b.onShareTimeline) ||
|
|
594
|
-
Component.enableShareTimeline) {
|
|
595
|
-
componentObj.methods.onShareTimeline = function () {
|
|
596
|
-
return safeExecute(this.compId, 'onShareTimeline');
|
|
597
|
-
};
|
|
598
|
-
}
|
|
599
|
-
return componentObj;
|
|
426
|
+
const getNativeCompId = incrementId();
|
|
427
|
+
let h;
|
|
428
|
+
let ReactDOM;
|
|
429
|
+
function initNativeComponentEntry(R, ReactDOM) {
|
|
430
|
+
class NativeComponentWrapper extends R.Component {
|
|
431
|
+
constructor() {
|
|
432
|
+
super(...arguments);
|
|
433
|
+
this.root = R.createRef();
|
|
434
|
+
this.ctx = this.props.getCtx();
|
|
435
|
+
}
|
|
436
|
+
componentDidMount() {
|
|
437
|
+
this.ctx.component = this;
|
|
438
|
+
const rootElement = this.root.current;
|
|
439
|
+
rootElement.ctx = this.ctx;
|
|
440
|
+
rootElement.performUpdate(true);
|
|
441
|
+
}
|
|
442
|
+
render() {
|
|
443
|
+
return (h('root', {
|
|
444
|
+
ref: this.root
|
|
445
|
+
}, this.props.renderComponent(this.ctx)));
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
class Entry extends R.Component {
|
|
449
|
+
constructor() {
|
|
450
|
+
super(...arguments);
|
|
451
|
+
this.state = {
|
|
452
|
+
components: []
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
componentDidMount() {
|
|
456
|
+
Current.app = this;
|
|
457
|
+
}
|
|
458
|
+
mount(Component, compId, getCtx) {
|
|
459
|
+
const isReactComponent = isClassComponent(R, Component);
|
|
460
|
+
const inject = (node) => node && injectPageInstance(node, compId);
|
|
461
|
+
const refs = isReactComponent ? { ref: inject } : {
|
|
462
|
+
forwardedRef: inject,
|
|
463
|
+
reactReduxForwardedRef: inject
|
|
464
|
+
};
|
|
465
|
+
if (reactMeta.PageContext === EMPTY_OBJ) {
|
|
466
|
+
reactMeta.PageContext = R.createContext('');
|
|
467
|
+
}
|
|
468
|
+
const item = {
|
|
469
|
+
compId,
|
|
470
|
+
element: h(NativeComponentWrapper, {
|
|
471
|
+
key: compId,
|
|
472
|
+
getCtx,
|
|
473
|
+
renderComponent(ctx) {
|
|
474
|
+
return h(reactMeta.PageContext.Provider, { value: compId }, h(Component, Object.assign(Object.assign(Object.assign({}, (ctx.data || (ctx.data = {})).props), refs), { $scope: ctx })));
|
|
475
|
+
}
|
|
476
|
+
})
|
|
477
|
+
};
|
|
478
|
+
this.setState({
|
|
479
|
+
components: [...this.state.components, item]
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
unmount(compId) {
|
|
483
|
+
const components = this.state.components;
|
|
484
|
+
const index = components.findIndex(item => item.compId === compId);
|
|
485
|
+
const next = [...components.slice(0, index), ...components.slice(index + 1)];
|
|
486
|
+
this.setState({
|
|
487
|
+
components: next
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
render() {
|
|
491
|
+
const components = this.state.components;
|
|
492
|
+
return (components.map(({ element }) => element));
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
setReconciler(ReactDOM);
|
|
496
|
+
const app = document.getElementById('app');
|
|
497
|
+
ReactDOM.render(h(Entry, {}), app);
|
|
498
|
+
}
|
|
499
|
+
function createNativeComponentConfig(Component, react, reactdom, componentConfig) {
|
|
500
|
+
var _a, _b;
|
|
501
|
+
reactMeta.R = react;
|
|
502
|
+
h = react.createElement;
|
|
503
|
+
ReactDOM = reactdom;
|
|
504
|
+
setReconciler(ReactDOM);
|
|
505
|
+
const componentObj = {
|
|
506
|
+
options: componentConfig,
|
|
507
|
+
properties: {
|
|
508
|
+
props: {
|
|
509
|
+
type: null,
|
|
510
|
+
value: null,
|
|
511
|
+
observer(_newVal, oldVal) {
|
|
512
|
+
oldVal && this.component.forceUpdate();
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
},
|
|
516
|
+
created() {
|
|
517
|
+
if (!Current.app) {
|
|
518
|
+
initNativeComponentEntry(react, ReactDOM);
|
|
519
|
+
}
|
|
520
|
+
},
|
|
521
|
+
attached() {
|
|
522
|
+
const compId = this.compId = getNativeCompId();
|
|
523
|
+
setCurrent(compId);
|
|
524
|
+
this.config = componentConfig;
|
|
525
|
+
Current.app.mount(Component, compId, () => this);
|
|
526
|
+
},
|
|
527
|
+
ready() {
|
|
528
|
+
safeExecute(this.compId, 'onReady');
|
|
529
|
+
},
|
|
530
|
+
detached() {
|
|
531
|
+
Current.app.unmount(this.compId);
|
|
532
|
+
},
|
|
533
|
+
pageLifetimes: {
|
|
534
|
+
show(options) {
|
|
535
|
+
safeExecute(this.compId, 'onShow', options);
|
|
536
|
+
},
|
|
537
|
+
hide() {
|
|
538
|
+
safeExecute(this.compId, 'onHide');
|
|
539
|
+
}
|
|
540
|
+
},
|
|
541
|
+
methods: {
|
|
542
|
+
eh: eventHandler
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
function setCurrent(compId) {
|
|
546
|
+
const pages = getCurrentPages();
|
|
547
|
+
const currentPage = pages[pages.length - 1];
|
|
548
|
+
if (Current.page === currentPage)
|
|
549
|
+
return;
|
|
550
|
+
Current.page = currentPage;
|
|
551
|
+
const route = currentPage.route || currentPage.__route__;
|
|
552
|
+
const router = {
|
|
553
|
+
params: currentPage.options || {},
|
|
554
|
+
path: addLeadingSlash(route),
|
|
555
|
+
$taroPath: compId,
|
|
556
|
+
onReady: '',
|
|
557
|
+
onHide: '',
|
|
558
|
+
onShow: ''
|
|
559
|
+
};
|
|
560
|
+
Current.router = router;
|
|
561
|
+
if (!currentPage.options) {
|
|
562
|
+
// 例如在微信小程序中,页面 options 的设置时机比组件 attached 慢
|
|
563
|
+
Object.defineProperty(currentPage, 'options', {
|
|
564
|
+
enumerable: true,
|
|
565
|
+
configurable: true,
|
|
566
|
+
get() {
|
|
567
|
+
return this._optionsValue;
|
|
568
|
+
},
|
|
569
|
+
set(value) {
|
|
570
|
+
router.params = value;
|
|
571
|
+
this._optionsValue = value;
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
// onShareAppMessage 和 onShareTimeline 一样,会影响小程序右上方按钮的选项,因此不能默认注册。
|
|
577
|
+
if (Component.onShareAppMessage ||
|
|
578
|
+
((_a = Component.prototype) === null || _a === void 0 ? void 0 : _a.onShareAppMessage) ||
|
|
579
|
+
Component.enableShareAppMessage) {
|
|
580
|
+
componentObj.methods.onShareAppMessage = function (options) {
|
|
581
|
+
const target = options === null || options === void 0 ? void 0 : options.target;
|
|
582
|
+
if (target) {
|
|
583
|
+
const id = target.id;
|
|
584
|
+
const element = document.getElementById(id);
|
|
585
|
+
if (element) {
|
|
586
|
+
target.dataset = element.dataset;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
return safeExecute(this.compId, 'onShareAppMessage', options);
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
if (Component.onShareTimeline ||
|
|
593
|
+
((_b = Component.prototype) === null || _b === void 0 ? void 0 : _b.onShareTimeline) ||
|
|
594
|
+
Component.enableShareTimeline) {
|
|
595
|
+
componentObj.methods.onShareTimeline = function () {
|
|
596
|
+
return safeExecute(this.compId, 'onShareTimeline');
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
return componentObj;
|
|
600
600
|
}
|
|
601
601
|
|
|
602
|
-
hooks.tap('initNativeApi', function (taro) {
|
|
603
|
-
for (const hook in taroHooks$1) {
|
|
604
|
-
taro[hook] = taroHooks$1[hook];
|
|
605
|
-
}
|
|
606
|
-
});
|
|
607
|
-
if (__TARO_FRAMEWORK__ === 'preact') {
|
|
608
|
-
const options = require('preact').options;
|
|
609
|
-
const oldVNodeHook = options.vnode;
|
|
610
|
-
const oldDiffedHook = options.diffed;
|
|
611
|
-
options.vnode = vnode => {
|
|
612
|
-
const { type, props } = vnode;
|
|
613
|
-
let normalizedProps = props;
|
|
614
|
-
// only normalize props on Element nodes
|
|
615
|
-
if (typeof type === 'string') {
|
|
616
|
-
normalizedProps = {};
|
|
617
|
-
for (let i in props) {
|
|
618
|
-
const value = props[i];
|
|
619
|
-
if (/^on/.test(i)) {
|
|
620
|
-
i = i.toLowerCase();
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
if (
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
else if (type === 'blur') {
|
|
661
|
-
e.type = 'focusout';
|
|
662
|
-
}
|
|
663
|
-
});
|
|
664
|
-
// hooks.modifyDispatchEventImpls?.push(e => {
|
|
665
|
-
// })
|
|
602
|
+
hooks.tap('initNativeApi', function (taro) {
|
|
603
|
+
for (const hook in taroHooks$1) {
|
|
604
|
+
taro[hook] = taroHooks$1[hook];
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
if (__TARO_FRAMEWORK__ === 'preact') {
|
|
608
|
+
const options = require('preact').options;
|
|
609
|
+
const oldVNodeHook = options.vnode;
|
|
610
|
+
const oldDiffedHook = options.diffed;
|
|
611
|
+
options.vnode = vnode => {
|
|
612
|
+
const { type, props } = vnode;
|
|
613
|
+
let normalizedProps = props;
|
|
614
|
+
// only normalize props on Element nodes
|
|
615
|
+
if (typeof type === 'string') {
|
|
616
|
+
normalizedProps = {};
|
|
617
|
+
for (let i in props) {
|
|
618
|
+
const value = props[i];
|
|
619
|
+
if (/^on/.test(i)) {
|
|
620
|
+
i = i.toLowerCase();
|
|
621
|
+
}
|
|
622
|
+
normalizedProps[i] = value;
|
|
623
|
+
}
|
|
624
|
+
vnode.props = normalizedProps;
|
|
625
|
+
}
|
|
626
|
+
if (oldVNodeHook)
|
|
627
|
+
oldVNodeHook(vnode);
|
|
628
|
+
};
|
|
629
|
+
options.diffed = function (newVNode) {
|
|
630
|
+
const dom = newVNode._dom;
|
|
631
|
+
const newVNodeProps = newVNode.props;
|
|
632
|
+
if (dom) { /** ElementNode */
|
|
633
|
+
for (const propName in newVNodeProps) {
|
|
634
|
+
const propValue = newVNodeProps[propName];
|
|
635
|
+
if (propValue === false && dom.props[propName] === undefined) {
|
|
636
|
+
// 值为 false 的属性在 Preact 的 diff 中被 removeAttribute 了,这里手动 setAttribute
|
|
637
|
+
// fix https://github.com/NervJS/taro/issues/11197
|
|
638
|
+
dom.setAttribute(propName, propValue);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
if (oldDiffedHook)
|
|
643
|
+
oldDiffedHook(newVNode);
|
|
644
|
+
};
|
|
645
|
+
hooks.tap('modifyMpEvent', e => {
|
|
646
|
+
const type = e.type;
|
|
647
|
+
if (type === 'tap') {
|
|
648
|
+
e.type = 'click';
|
|
649
|
+
}
|
|
650
|
+
else if (type === 'focus') {
|
|
651
|
+
// 兼容 preact/compat/src/render.js options.vnode 的处理逻辑
|
|
652
|
+
e.type = 'focusin';
|
|
653
|
+
}
|
|
654
|
+
else if (type === 'blur') {
|
|
655
|
+
e.type = 'focusout';
|
|
656
|
+
}
|
|
657
|
+
});
|
|
658
|
+
// hooks.modifyDispatchEventImpls?.push(e => {
|
|
659
|
+
// })
|
|
666
660
|
}
|
|
667
661
|
|
|
668
662
|
export { connectReactPage, createNativeComponentConfig, createReactApp, setReconciler, useAddToFavorites, useDidHide, useDidShow, useError, useLaunch, useLoad, useOptionMenuClick, usePageNotFound, usePageScroll, usePullDownRefresh, usePullIntercept, useReachBottom, useReady, useResize, useRouter, useSaveExitState, useScope, useShareAppMessage, useShareTimeline, useTabItemTap, useTitleClick, useUnload };
|