@tarojs/plugin-platform-harmony-ets 4.0.0-alpha.0 → 4.0.0-alpha.11

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.
Files changed (139) hide show
  1. package/dist/apis/base/system.ts +73 -20
  2. package/dist/apis/canvas/index.ts +10 -1
  3. package/dist/apis/device/clipboard.ts +16 -8
  4. package/dist/apis/device/memory.ts +10 -3
  5. package/dist/apis/framework/index.ts +1 -5
  6. package/dist/apis/index.ts +27 -17
  7. package/dist/apis/media/image/index.ts +1 -1
  8. package/dist/apis/media/video/VideoContext.ts +56 -7
  9. package/dist/apis/media/video/index.ts +3 -2
  10. package/dist/apis/network/request.ts +5 -5
  11. package/dist/apis/route/index.ts +15 -0
  12. package/dist/apis/storage/index.ts +146 -78
  13. package/dist/apis/ui/animation/animation.ts +71 -29
  14. package/dist/apis/ui/background.ts +2 -1
  15. package/dist/apis/ui/interaction/index.ts +42 -59
  16. package/dist/apis/ui/navigation-bar/index.ts +1 -1
  17. package/dist/apis/ui/pull-down-refresh.ts +9 -3
  18. package/dist/apis/ui/scroll/index.ts +5 -5
  19. package/dist/apis/ui/tab-bar.ts +3 -3
  20. package/dist/apis/utils/index.ts +1 -1
  21. package/dist/apis/wxml/IntersectionObserver.ts +18 -10
  22. package/dist/apis/wxml/index.ts +2 -0
  23. package/dist/apis/wxml/selectorQuery.ts +26 -13
  24. package/dist/components-harmony-ets/button.ets +68 -68
  25. package/dist/components-harmony-ets/canvas.ets +51 -0
  26. package/dist/components-harmony-ets/checkbox.ets +81 -102
  27. package/dist/components-harmony-ets/form.ets +54 -45
  28. package/dist/components-harmony-ets/icon.ets +34 -50
  29. package/dist/components-harmony-ets/image.ets +35 -45
  30. package/dist/components-harmony-ets/index.ets +92 -0
  31. package/dist/components-harmony-ets/innerHtml.ets +11 -6
  32. package/dist/components-harmony-ets/input.ets +51 -67
  33. package/dist/components-harmony-ets/label.ets +73 -53
  34. package/dist/components-harmony-ets/listView.ets +26 -0
  35. package/dist/components-harmony-ets/movableArea.ets +124 -0
  36. package/dist/components-harmony-ets/movableView.ets +93 -0
  37. package/dist/components-harmony-ets/navigationBar.ets +65 -0
  38. package/dist/components-harmony-ets/pageMeta.ets +94 -0
  39. package/dist/components-harmony-ets/picker.ets +74 -77
  40. package/dist/components-harmony-ets/progress.ets +52 -0
  41. package/dist/components-harmony-ets/pseudo.ets +80 -0
  42. package/dist/components-harmony-ets/radio.ets +82 -104
  43. package/dist/components-harmony-ets/richText.ets +20 -68
  44. package/dist/components-harmony-ets/scrollList.ets +94 -0
  45. package/dist/components-harmony-ets/scrollView.ets +67 -103
  46. package/dist/components-harmony-ets/slider.ets +23 -47
  47. package/dist/components-harmony-ets/stickySection.ets +42 -0
  48. package/dist/components-harmony-ets/style.ets +396 -0
  49. package/dist/components-harmony-ets/swiper.ets +64 -53
  50. package/dist/components-harmony-ets/switch.ets +44 -55
  51. package/dist/components-harmony-ets/{index.ts → tag.ts} +6 -0
  52. package/dist/components-harmony-ets/text.ets +134 -75
  53. package/dist/components-harmony-ets/textArea.ets +54 -62
  54. package/dist/components-harmony-ets/utils/AttributeManager.ets +1 -1
  55. package/dist/components-harmony-ets/utils/DynamicCenter.ts +4 -13
  56. package/dist/components-harmony-ets/utils/flexManager.ets +76 -8
  57. package/dist/components-harmony-ets/utils/helper.ets +20 -7
  58. package/dist/components-harmony-ets/utils/htmlParser/HarmonyHTMLParser.ts +1 -2
  59. package/dist/components-harmony-ets/utils/htmlParser/index.ts +1 -1
  60. package/dist/components-harmony-ets/utils/index.ts +54 -50
  61. package/dist/components-harmony-ets/utils/styles.ets +178 -63
  62. package/dist/components-harmony-ets/video.ets +37 -54
  63. package/dist/components-harmony-ets/view.ets +63 -94
  64. package/dist/components-harmony-ets/webView.ets +56 -0
  65. package/dist/index.d.ts +152 -0
  66. package/dist/index.js +199 -58
  67. package/dist/index.js.map +1 -1
  68. package/dist/runtime-ets/bom/document.ts +6 -4
  69. package/dist/runtime-ets/bom/getComputedStyle.ts +2 -2
  70. package/dist/runtime-ets/bom/window.ts +9 -2
  71. package/dist/runtime-ets/current.ts +3 -0
  72. package/dist/runtime-ets/dom/bind.ts +28 -12
  73. package/dist/runtime-ets/dom/class-list.ts +2 -2
  74. package/dist/runtime-ets/dom/cssNesting.ts +409 -0
  75. package/dist/runtime-ets/dom/cssStyleDeclaration.ts +29 -19
  76. package/dist/runtime-ets/dom/document.ts +22 -8
  77. package/dist/runtime-ets/dom/element/canvas.ts +136 -0
  78. package/dist/runtime-ets/dom/element/element.ts +334 -57
  79. package/dist/runtime-ets/dom/element/form.ts +32 -26
  80. package/dist/runtime-ets/dom/element/index.ts +33 -2
  81. package/dist/runtime-ets/dom/element/movableArea.ts +11 -0
  82. package/dist/runtime-ets/dom/element/movableView.ts +242 -0
  83. package/dist/runtime-ets/dom/element/normal.ts +36 -8
  84. package/dist/runtime-ets/dom/element/progress.ts +11 -0
  85. package/dist/runtime-ets/dom/element/scrollView.ts +1 -0
  86. package/dist/runtime-ets/dom/element/text.ts +1 -8
  87. package/dist/runtime-ets/dom/element/video.ts +5 -4
  88. package/dist/runtime-ets/dom/element/webView.ts +68 -0
  89. package/dist/runtime-ets/dom/event.ts +2 -4
  90. package/dist/runtime-ets/dom/eventTarget.ts +2 -3
  91. package/dist/runtime-ets/dom/node.ts +62 -27
  92. package/dist/runtime-ets/dom/stylesheet/covertWeb2Hm.ts +805 -0
  93. package/dist/runtime-ets/dom/stylesheet/index.ts +98 -518
  94. package/dist/runtime-ets/dom/stylesheet/type.ts +92 -17
  95. package/dist/runtime-ets/dom/stylesheet/util.ts +74 -16
  96. package/dist/runtime-ets/index.ts +2 -2
  97. package/dist/runtime-ets/interface/event.ts +3 -2
  98. package/dist/runtime-ets/utils/index.ts +77 -12
  99. package/dist/runtime-ets/utils/info.ts +4 -2
  100. package/dist/runtime-framework/react/app.ts +17 -22
  101. package/dist/runtime-framework/react/hooks.ts +3 -4
  102. package/dist/runtime-framework/react/index.ts +1 -2
  103. package/dist/runtime-framework/react/native-page.ts +421 -0
  104. package/dist/runtime-framework/react/page.ts +4 -9
  105. package/dist/runtime-framework/solid/app.ts +25 -45
  106. package/dist/runtime-framework/solid/connect.ts +21 -3
  107. package/dist/runtime-framework/solid/hooks.ts +17 -12
  108. package/dist/runtime-framework/solid/index.ts +6 -2
  109. package/dist/runtime-framework/solid/page.ts +84 -30
  110. package/dist/runtime-framework/solid/reconciler/props.ts +70 -25
  111. package/dist/runtime-framework/solid/reconciler/render.ts +16 -6
  112. package/dist/runtime-framework/solid/reconciler/use.ts +0 -1
  113. package/dist/runtime-framework/solid/utils/index.ts +0 -2
  114. package/dist/runtime-utils.d.ts +827 -0
  115. package/dist/runtime-utils.js +510 -237
  116. package/dist/runtime-utils.js.map +1 -1
  117. package/dist/runtime.d.ts +1 -0
  118. package/dist/runtime.js +510 -237
  119. package/dist/runtime.js.map +1 -1
  120. package/index.js +3 -1
  121. package/package.json +14 -15
  122. package/static/media/cancel.svg +1 -0
  123. package/static/media/circle.svg +1 -0
  124. package/static/media/clear.svg +1 -0
  125. package/static/media/download.svg +1 -0
  126. package/static/media/info.svg +1 -0
  127. package/static/media/info_circle.svg +1 -0
  128. package/static/media/search.svg +1 -0
  129. package/static/media/success.svg +1 -0
  130. package/static/media/success_no_circle.svg +1 -0
  131. package/static/media/taro_arrow_left.svg +1 -0
  132. package/static/media/taro_home.svg +1 -0
  133. package/static/media/waiting.svg +1 -0
  134. package/static/media/warn.svg +1 -0
  135. package/types/harmony.d.ts +4 -0
  136. package/types/index.d.ts +4 -0
  137. package/types/runtime.d.ts +3 -1
  138. package/dist/runtime-ets/utils/bind.ts +0 -24
  139. /package/dist/runtime-framework/solid/{contant.ts → constant.ts} +0 -0
@@ -0,0 +1,421 @@
1
+ import { Current, document, requestAnimationFrame, TaroElement, window } from '@tarojs/runtime' // eslint-disable-line import/no-duplicates
2
+ import { addLeadingSlash, CONTEXT_ACTIONS, env, eventCenter, TFunc } from '@tarojs/runtime/dist/runtime.esm' // eslint-disable-line import/no-duplicates
3
+ import { ensure, hooks, isUndefined } from '@tarojs/shared'
4
+
5
+ import { ReactMeta as reactMeta } from './app'
6
+ import { setReconciler } from './connect'
7
+ import { ON_HIDE, ON_READY, ON_SHOW } from './constant'
8
+ import {
9
+ getOnHideEventKey,
10
+ getOnReadyEventKey,
11
+ getOnShowEventKey,
12
+ getPath,
13
+ injectPageInstance,
14
+ removePageInstance,
15
+ safeExecute,
16
+ } from './page'
17
+ import { EMPTY_OBJ, incrementId, isClassComponent } from './utils'
18
+
19
+ import type { AppInstance } from '@tarojs/taro'
20
+ import type * as React from 'react'
21
+
22
+ const getNativeCompId = incrementId()
23
+ let h: typeof React.createElement
24
+ let ReactDOM
25
+ let nativeComponentApp: AppInstance
26
+ interface InitNativeComponentEntryParams {
27
+ R: typeof React
28
+ ReactDOM: typeof ReactDOM
29
+ cb?: TFunc
30
+ // 是否使用默认的 DOM 入口 - app;默认为true,false的时候,会创建一个新的dom并且把它挂载在 app 下面
31
+ isDefaultEntryDom?: boolean
32
+ }
33
+
34
+ function initNativeComponentEntry (params: InitNativeComponentEntryParams) {
35
+ const { R, ReactDOM, cb, isDefaultEntryDom = true } = params
36
+ interface IEntryState {
37
+ components: {
38
+ compId: string
39
+ element: React.ReactElement
40
+ }[]
41
+ }
42
+
43
+ interface IWrapperProps {
44
+ compId: string
45
+ getCtx: () => any
46
+ renderComponent: (ctx: any) => React.ReactElement
47
+ }
48
+
49
+ class NativeComponentWrapper extends R.Component<IWrapperProps, Record<any, any>> {
50
+ root = R.createRef<TaroElement>()
51
+ ctx = this.props.getCtx()
52
+
53
+ componentDidMount () {
54
+ this.ctx.component = this
55
+ if (this.root.current) {
56
+ this.root.current = this.ctx
57
+ }
58
+ }
59
+
60
+ // React 16 uncaught error 会导致整个应用 crash,
61
+ // 目前把错误缩小到页面
62
+ componentDidCatch (error, info: React.ErrorInfo) {
63
+ console.warn(error)
64
+ console.error(info.componentStack)
65
+ }
66
+
67
+ render () {
68
+ return h(
69
+ 'view',
70
+ {
71
+ ref: this.root,
72
+ id: this.props.compId,
73
+ },
74
+ this.props.renderComponent(this.ctx)
75
+ )
76
+ }
77
+ }
78
+
79
+ class Entry extends R.Component<Record<any, any>, IEntryState> {
80
+ state: IEntryState = {
81
+ components: [],
82
+ }
83
+
84
+ componentDidMount () {
85
+ if (isDefaultEntryDom) {
86
+ if (Current.app) {
87
+ Current.app = Object.assign(this, Current.app)
88
+ } else {
89
+ Current.app = this
90
+ }
91
+ } else {
92
+ nativeComponentApp = this
93
+ }
94
+ cb && cb()
95
+ }
96
+
97
+ // React 16 uncaught error 会导致整个应用 crash,
98
+ // 目前把错误缩小到页面
99
+ componentDidCatch (error, info: React.ErrorInfo) {
100
+ console.warn(error)
101
+ console.error(info.componentStack)
102
+ }
103
+
104
+ mount (Component, compId, getCtx, cb?) {
105
+ const isReactComponent = isClassComponent(R, Component)
106
+ const inject = (node?: any) => node && injectPageInstance(node, compId)
107
+ const refs = isReactComponent
108
+ ? { ref: inject }
109
+ : {
110
+ forwardedRef: inject,
111
+ reactReduxForwardedRef: inject,
112
+ }
113
+ if (reactMeta.PageContext === EMPTY_OBJ) {
114
+ reactMeta.PageContext = R.createContext('')
115
+ }
116
+ const item = {
117
+ compId,
118
+ element: h(NativeComponentWrapper, {
119
+ key: compId,
120
+ compId,
121
+ getCtx,
122
+ renderComponent (ctx) {
123
+ return h(
124
+ reactMeta.PageContext.Provider,
125
+ { value: compId },
126
+ h(Component, {
127
+ // TODO: 传递 Props
128
+ ...(ctx.props || {}),
129
+ ...refs,
130
+ $scope: ctx,
131
+ })
132
+ )
133
+ },
134
+ }),
135
+ }
136
+ this.setState(
137
+ {
138
+ components: [...this.state.components, item],
139
+ },
140
+ () => cb && cb()
141
+ )
142
+ }
143
+
144
+ unmount (compId, cb?) {
145
+ const components = this.state.components
146
+ const index = components.findIndex((item) => item.compId === compId)
147
+ const next = [...components.slice(0, index), ...components.slice(index + 1)]
148
+ this.setState(
149
+ {
150
+ components: next,
151
+ },
152
+ () => {
153
+ removePageInstance(compId)
154
+ cb && cb()
155
+ }
156
+ )
157
+ }
158
+
159
+ render () {
160
+ const components = this.state.components
161
+
162
+ return components.map(({ element }) => element)
163
+ }
164
+ }
165
+
166
+ setReconciler(ReactDOM)
167
+
168
+ let app = document.getElementById('app')
169
+ if (!isDefaultEntryDom && !nativeComponentApp) {
170
+ // create
171
+ const nativeApp = document.createElement('nativeComponent')
172
+ // insert
173
+ app?.appendChild(nativeApp)
174
+ app = nativeApp
175
+ }
176
+ // eslint-disable-next-line react/no-deprecated
177
+ ReactDOM.render(h(Entry, {}), app)
178
+ }
179
+
180
+ export function createNativePageConfig (
181
+ Component,
182
+ pageName: string,
183
+ react: typeof React,
184
+ reactDOM: typeof ReactDOM,
185
+ pageConfig
186
+ ) {
187
+ reactMeta.R = react
188
+ h = react.createElement
189
+ ReactDOM = reactDOM
190
+ setReconciler(ReactDOM)
191
+ const [ONLOAD, ONUNLOAD, ONREADY, ONSHOW, ONHIDE, LIFECYCLES, SIDE_EFFECT_LIFECYCLES] =
192
+ hooks.call('getMiniLifecycleImpl')!.page
193
+ let unmounting = false
194
+ let prepareMountList: (() => void)[] = []
195
+ let pageElement: TaroElement | null = null
196
+ let loadResolver: (...args: unknown[]) => void
197
+ let hasLoaded: Promise<void>
198
+ const id = pageName ?? `taro_page_${getNativeCompId()}`
199
+ function setCurrentRouter (page) {
200
+ const router = page.route || page.__route__ || page.$taroPath
201
+ Current.router = {
202
+ params: page.$taroParams!,
203
+ path: addLeadingSlash(router),
204
+ $taroPath: page.$taroPath,
205
+ onReady: getOnReadyEventKey(id),
206
+ onShow: getOnShowEventKey(id),
207
+ onHide: getOnHideEventKey(id),
208
+ }
209
+ if (!isUndefined(page.exitState)) {
210
+ Current.router.exitState = page.exitState
211
+ }
212
+ }
213
+
214
+ const pageObj: Record<string, any> = {
215
+ options: pageConfig,
216
+ [ONLOAD] (options: Readonly<Record<string, unknown>> = {}, cb?: TFunc) {
217
+ hasLoaded = new Promise((resolve) => {
218
+ loadResolver = resolve
219
+ })
220
+ Current.page = this as any
221
+ this.config = pageConfig || {}
222
+ // this.$taroPath 是页面唯一标识
223
+ const uniqueOptions = Object.assign({}, options, { $taroTimestamp: Date.now() })
224
+ const $taroPath = (this.$taroPath = getPath(id, uniqueOptions))
225
+
226
+ // this.$taroParams 作为暴露给开发者的页面参数对象,可以被随意修改
227
+ if (this.$taroParams == null) {
228
+ this.$taroParams = uniqueOptions
229
+ }
230
+
231
+ setCurrentRouter(this)
232
+ window.trigger(CONTEXT_ACTIONS.INIT, $taroPath)
233
+
234
+ const mountCallback = () => {
235
+ pageElement = document.getElementById($taroPath)
236
+
237
+ ensure(pageElement !== null, '没有找到页面实例。')
238
+
239
+ safeExecute($taroPath, ONLOAD, this.$taroParams)
240
+ loadResolver()
241
+ cb && cb(pageElement)
242
+ pageElement.ctx = this
243
+ }
244
+
245
+ const mount = () => {
246
+ if (!Current.app) {
247
+ initNativeComponentEntry({
248
+ R: react,
249
+ ReactDOM,
250
+ cb: () => {
251
+ Current.app!.mount!(Component, $taroPath, () => this, mountCallback)
252
+ },
253
+ })
254
+ } else {
255
+ Current.app!.mount!(Component, $taroPath, () => this, mountCallback)
256
+ }
257
+ }
258
+
259
+ if (unmounting) {
260
+ prepareMountList.push(mount)
261
+ } else {
262
+ mount()
263
+ }
264
+ },
265
+ [ONUNLOAD] () {
266
+ const $taroPath = this.$taroPath
267
+ // 销毁当前页面的上下文信息
268
+ window.trigger(CONTEXT_ACTIONS.DESTORY, $taroPath)
269
+ // 触发onUnload生命周期
270
+ safeExecute($taroPath, ONUNLOAD)
271
+ resetCurrent.call(this)
272
+ unmounting = true
273
+ Current.app!.unmount!($taroPath, () => {
274
+ unmounting = false
275
+ removePageInstance($taroPath)
276
+ if (pageElement) {
277
+ pageElement.ctx = null
278
+ pageElement = null
279
+ }
280
+ if (prepareMountList.length) {
281
+ prepareMountList.forEach((fn) => fn())
282
+ prepareMountList = []
283
+ }
284
+ })
285
+ },
286
+ [ONREADY] () {
287
+ hasLoaded.then(() => {
288
+ // 触发生命周期
289
+ safeExecute(this.$taroPath, ON_READY)
290
+ // 通过事件触发子组件的生命周期
291
+ requestAnimationFrame(() => eventCenter.trigger(getOnReadyEventKey(id)))
292
+ this.onReady = {}
293
+ this.onReady.called = true
294
+ })
295
+ },
296
+ [ONSHOW] (options = {}) {
297
+ hasLoaded.then(() => {
298
+ // 设置 Current 的 page 和 router
299
+ Current.page = this as any
300
+ setCurrentRouter(this)
301
+ // 恢复上下文信息
302
+ window.trigger(CONTEXT_ACTIONS.RECOVER, this.$taroPath)
303
+ // 触发生命周期
304
+ safeExecute(this.$taroPath, ON_SHOW, options)
305
+ // 通过事件触发子组件的生命周期
306
+ requestAnimationFrame(() => eventCenter.trigger(getOnShowEventKey(id)))
307
+ })
308
+ },
309
+ [ONHIDE] () {
310
+ // 缓存当前页面上下文信息
311
+ window.trigger(CONTEXT_ACTIONS.RESTORE, this.$taroPath)
312
+ // 设置 Current 的 page 和 router
313
+ if (Current.page === this) {
314
+ Current.page = null
315
+ Current.router = null
316
+ }
317
+ // 触发生命周期
318
+ safeExecute(this.$taroPath, ON_HIDE)
319
+ // 通过事件触发子组件的生命周期
320
+ eventCenter.trigger(getOnHideEventKey(id))
321
+ },
322
+ }
323
+
324
+ function resetCurrent () {
325
+ if (Current.page === this) {
326
+ // 小程序插件页面卸载之后返回到宿主页面时,需重置Current页面和路由。否则引发插件组件二次加载异常 fix:#11991
327
+ Current.page = null
328
+ Current.router = null
329
+ }
330
+ }
331
+
332
+ LIFECYCLES.forEach((lifecycle) => {
333
+ pageObj[lifecycle] = function () {
334
+ return safeExecute(this.$taroPath, lifecycle, ...arguments)
335
+ }
336
+ })
337
+
338
+ // onShareAppMessage 和 onShareTimeline 一样,会影响小程序右上方按钮的选项,因此不能默认注册。
339
+ SIDE_EFFECT_LIFECYCLES.forEach((lifecycle) => {
340
+ if (Component[lifecycle] || Component.prototype?.[lifecycle] || Component[lifecycle.replace(/^on/, 'enable')]) {
341
+ pageObj[lifecycle] = function (...args) {
342
+ const target = args[0]?.target
343
+ if (target?.id) {
344
+ const id = target.id
345
+ const element = env.document.getElementById(id)
346
+ if (element) {
347
+ target.dataset = element.dataset
348
+ }
349
+ }
350
+ return safeExecute(this.$taroPath, lifecycle, ...args)
351
+ }
352
+ }
353
+ })
354
+
355
+ hooks.call('modifyPageObject', pageObj)
356
+
357
+ return pageObj
358
+ }
359
+
360
+ export function createNativeComponentConfig (
361
+ Component,
362
+ react: typeof React,
363
+ reactdom,
364
+ componentConfig
365
+ ) {
366
+ reactMeta.R = react
367
+ h = react.createElement
368
+ ReactDOM = reactdom
369
+ setReconciler(ReactDOM)
370
+ const { isNewBlended } = componentConfig
371
+
372
+ const componentObj: Record<string, any> = {
373
+ options: componentConfig,
374
+ onLoad (
375
+ options: Readonly<Record<string, unknown>> = {}, // eslint-disable-line @typescript-eslint/no-unused-vars
376
+ cb?: TFunc
377
+ ) {
378
+ const app = isNewBlended ? nativeComponentApp : Current.app
379
+
380
+ const mountComponent = () => {
381
+ const app = isNewBlended ? nativeComponentApp : Current.app
382
+ const compId = (this.compId = getNativeCompId())
383
+
384
+ this.config = componentConfig
385
+ app!.mount!(
386
+ Component,
387
+ compId,
388
+ () => this,
389
+ () => {
390
+ const el = document.getElementById(compId)
391
+
392
+ if (!el) {
393
+ throw new Error(`没有找到组件实例。`)
394
+ } else {
395
+ el.ctx = this
396
+ cb && cb(el)
397
+ }
398
+ }
399
+ )
400
+ }
401
+
402
+ if (!app) {
403
+ initNativeComponentEntry({
404
+ R: react,
405
+ ReactDOM,
406
+ isDefaultEntryDom: !isNewBlended,
407
+ cb: mountComponent,
408
+ })
409
+ } else {
410
+ mountComponent()
411
+ }
412
+ },
413
+
414
+ onUnload () {
415
+ const app = isNewBlended ? nativeComponentApp : Current.app
416
+ app!.unmount!(this.compId)
417
+ },
418
+ }
419
+
420
+ return componentObj
421
+ }
@@ -1,5 +1,5 @@
1
1
  import { Current, document, requestAnimationFrame, window } from '@tarojs/runtime' // eslint-disable-line import/no-duplicates
2
- import { CONTEXT_ACTIONS, env, eventCenter } from '@tarojs/runtime/dist/runtime.esm' // eslint-disable-line import/no-duplicates
2
+ import { addLeadingSlash, CONTEXT_ACTIONS, env, eventCenter } from '@tarojs/runtime/dist/runtime.esm' // eslint-disable-line import/no-duplicates
3
3
  import { hooks, isArray, isFunction, isUndefined } from '@tarojs/shared'
4
4
 
5
5
  import { ON_HIDE, ON_LOAD, ON_READY, ON_SHOW, ON_UNLOAD } from './constant'
@@ -23,13 +23,6 @@ export function removePageInstance (id: string) {
23
23
  instances.delete(id)
24
24
  }
25
25
 
26
- export function addLeadingSlash (path?: string): string {
27
- if (path == null) {
28
- return ''
29
- }
30
- return path.charAt(0) === '/' ? path : '/' + path
31
- }
32
-
33
26
  export function safeExecute (path: string, lifecycle: string, ...args: unknown[]) {
34
27
  const instance = instances.get(path)
35
28
 
@@ -136,7 +129,8 @@ export function createPageConfig (component: any, pageName?: string, pageConfig?
136
129
  window.trigger(CONTEXT_ACTIONS.INIT, $taroPath)
137
130
 
138
131
  const mount = () => {
139
- Current.app!.mount!(component, $taroPath, () => {
132
+ // @ts-ignore
133
+ Current.app!.mount!(component, $taroPath, null, () => {
140
134
  pageElement = document.getElementById($taroPath)
141
135
 
142
136
  if (!pageElement) {
@@ -183,6 +177,7 @@ export function createPageConfig (component: any, pageName?: string, pageConfig?
183
177
  safeExecute(this.$taroPath, ON_READY)
184
178
  // 通过事件触发子组件的生命周期
185
179
  requestAnimationFrame(() => eventCenter.trigger(getOnReadyEventKey(id)))
180
+ this.onReady = {}
186
181
  this.onReady.called = true
187
182
  })
188
183
  },
@@ -1,17 +1,16 @@
1
- import { Current, document } from '@tarojs/runtime'
2
- import { hooks, isWebPlatform } from '@tarojs/shared'
1
+ import { createComponent, h, render } from '@tarojs/plugin-framework-react/dist/reconciler'
2
+ import { Current, document } from '@tarojs/runtime' // eslint-disable-line import/no-duplicates
3
+ import { eventCenter } from '@tarojs/runtime/dist/runtime.esm' // eslint-disable-line import/no-duplicates
4
+ import { hooks } from '@tarojs/shared'
3
5
  import { batch, createContext, createRoot, createSignal, For } from 'solid-js'
4
6
 
5
7
  import { setReconciler } from './connect'
6
8
  import { getPageInstance, injectPageInstance } from './page'
7
- import { createComponent, h, render } from './reconciler'
8
9
  import { EMPTY_OBJ, HOOKS_APP_ID, setDefaultDescriptor, setRouterParams } from './utils'
9
10
 
10
11
  import type { AppInstance, Instance, PageLifeCycle, PageProps, ReactAppInstance } from '@tarojs/runtime'
11
12
  import type { AppConfig } from '@tarojs/taro'
12
- import type { Component } from './connect'
13
-
14
- const isWeb = isWebPlatform()
13
+ import type { SolidComponent } from './connect'
15
14
 
16
15
  export const ReactMeta = {
17
16
  R: EMPTY_OBJ,
@@ -19,7 +18,7 @@ export const ReactMeta = {
19
18
  PageContext: EMPTY_OBJ
20
19
  }
21
20
 
22
- export function createSolidApp(App: Component, config: AppConfig) {
21
+ export function createSolidApp(App: SolidComponent, config: AppConfig) {
23
22
  setReconciler()
24
23
 
25
24
  if (ReactMeta.PageContext === EMPTY_OBJ) {
@@ -32,10 +31,7 @@ export function createSolidApp(App: Component, config: AppConfig) {
32
31
  }
33
32
 
34
33
  function renderReactRoot() {
35
- let appId = 'app'
36
- if (isWeb) {
37
- appId = config?.appId || appId
38
- }
34
+ const appId = 'app'
39
35
 
40
36
  if (ReactMeta.Container === EMPTY_OBJ) {
41
37
  const Container = document.createElement('view')
@@ -48,17 +44,18 @@ export function createSolidApp(App: Component, config: AppConfig) {
48
44
  render(AppWrapper, root)
49
45
  }
50
46
  const [pages, setPages] = createSignal<any[]>([])
47
+ const [elements, setElements] = createSignal<any[]>([])
51
48
 
52
49
  function AppWrapper () {
53
50
  appRef = {} as unknown as ReactAppInstance
54
51
  return createComponent(App, {
55
- children: createComponent(For as unknown as Component, {
52
+ children: createComponent(For as unknown as SolidComponent, {
56
53
  get each() {
57
54
  return pages()
58
55
  },
59
56
  children: ({ id, component }) => {
60
57
  const children = () =>
61
- createComponent(ReactMeta.PageContext.Provider as unknown as Component, {
58
+ createComponent(ReactMeta.PageContext.Provider as unknown as SolidComponent, {
62
59
  value: id,
63
60
  children: () => {
64
61
  injectPageInstance(
@@ -71,38 +68,29 @@ export function createSolidApp(App: Component, config: AppConfig) {
71
68
  },
72
69
  })
73
70
 
74
- if (isWeb) {
75
- return h('div', { id, className: 'taro_page' }, children)
76
- } else {
77
- return h('root', { id }, children)
78
- }
71
+ return h('root', { id }, children)
79
72
  },
80
73
  }),
81
74
  })
82
75
  }
83
76
 
84
- if (!isWeb) {
85
- renderReactRoot()
86
- }
87
-
88
- const [ONLAUNCH, ONSHOW, ONHIDE] = hooks.call('getMiniLifecycleImpl')!.app
77
+ renderReactRoot()
89
78
 
90
- const appObj: AppInstance = Object.create(
79
+ const app: AppInstance = Object.create(
91
80
  {
92
- mount(component: Component, id: string, cb: () => void) {
81
+ mount(component: SolidComponent, id: string, cb: () => void) {
93
82
  setPages((old) => [
94
83
  ...old,
95
84
  { id, component },
96
85
  ])
97
86
  batch(cb)
98
87
  },
99
-
100
88
  unmount(id: string, cb: () => void) {
101
- setPages(
102
- pages().filter((item) => {
103
- return item.id !== id
104
- })
105
- )
89
+ const idx = elements().findIndex((item) => item.id === id)
90
+ setElements((old) => {
91
+ old.splice(idx, 1)
92
+ return old
93
+ })
106
94
  batch(cb)
107
95
  },
108
96
  },
@@ -112,15 +100,10 @@ export function createSolidApp(App: Component, config: AppConfig) {
112
100
  value: config,
113
101
  }),
114
102
 
115
- [ONLAUNCH]: setDefaultDescriptor({
103
+ onLaunch: setDefaultDescriptor({
116
104
  value(options) {
117
105
  setRouterParams(options)
118
106
 
119
- if (isWeb) {
120
- // 由于 H5 路由初始化的时候会清除 app 下的 dom 元素,所以需要在路由初始化后执行 render
121
- renderReactRoot()
122
- }
123
-
124
107
  const onLaunch = () => {
125
108
  const app = getAppInstance()
126
109
 
@@ -151,28 +134,25 @@ export function createSolidApp(App: Component, config: AppConfig) {
151
134
 
152
135
  onLaunch()
153
136
  triggerAppHook('onLaunch', options)
137
+ eventCenter.trigger('__taroRouterLaunch', options)
154
138
  },
155
139
  }),
156
-
157
- [ONSHOW]: setDefaultDescriptor({
140
+ onShow: setDefaultDescriptor({
158
141
  value(options) {
159
142
  setRouterParams(options)
160
143
  triggerAppHook('onShow', options)
161
144
  },
162
145
  }),
163
-
164
- [ONHIDE]: setDefaultDescriptor({
146
+ onHide: setDefaultDescriptor({
165
147
  value() {
166
148
  triggerAppHook('onHide')
167
149
  },
168
150
  }),
169
-
170
151
  onError: setDefaultDescriptor({
171
152
  value(error: string) {
172
153
  triggerAppHook('onError', error)
173
154
  },
174
155
  }),
175
-
176
156
  onPageNotFound: setDefaultDescriptor({
177
157
  value(res: unknown) {
178
158
  triggerAppHook('onPageNotFound', res)
@@ -195,6 +175,6 @@ export function createSolidApp(App: Component, config: AppConfig) {
195
175
  }
196
176
  }
197
177
 
198
- Current.app = appObj
199
- return appObj
178
+ Current.app = app
179
+ return app
200
180
  }
@@ -1,11 +1,29 @@
1
- import { TaroNode } from '@tarojs/runtime'
2
1
  import { hooks } from '@tarojs/shared'
3
2
  import { batch } from 'solid-js'
4
3
 
5
- export type Component = (props?: any) => TaroNode
4
+ import { ensureIsArray } from './utils'
6
5
 
7
- export function setReconciler() {
6
+ import type { TaroNode } from '@tarojs/runtime'
7
+
8
+ export type SolidComponent = (props?: any) => TaroNode
9
+
10
+ export function setReconciler () {
8
11
  hooks.tap('batchedEventUpdates', function (cb) {
9
12
  batch(cb)
10
13
  })
14
+
15
+ hooks.tap('mergePageInstance', function (prev, next) {
16
+ if (!prev || !next) return
17
+
18
+ // 子组件使用 lifecycle hooks 注册了生命周期后,会存在 prev,里面是注册的生命周期回调。
19
+
20
+ // prev 使用 Object.create(null) 创建,H5 的 fast-refresh 可能也会导致存在 prev,要排除这些意外产生的 prev
21
+ if ('constructor' in prev) return
22
+
23
+ Object.keys(prev).forEach(item => {
24
+ const prevList = prev[item]
25
+ const nextList = ensureIsArray<() => any>(next[item])
26
+ next[item] = nextList.concat(prevList)
27
+ })
28
+ })
11
29
  }