@tarojs/plugin-platform-harmony-ets 4.0.0-beta.11 → 4.0.0-beta.111

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 (129) 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/framework/index.ts +1 -5
  5. package/dist/apis/index.ts +25 -17
  6. package/dist/apis/media/image/index.ts +1 -1
  7. package/dist/apis/storage/index.ts +135 -131
  8. package/dist/apis/ui/animation/animation.ts +71 -29
  9. package/dist/apis/ui/background.ts +2 -1
  10. package/dist/apis/ui/interaction/index.ts +42 -59
  11. package/dist/apis/ui/navigation-bar/index.ts +1 -1
  12. package/dist/apis/ui/pull-down-refresh.ts +9 -3
  13. package/dist/apis/ui/scroll/index.ts +5 -5
  14. package/dist/apis/ui/tab-bar.ts +3 -3
  15. package/dist/apis/utils/index.ts +2 -1
  16. package/dist/apis/wxml/IntersectionObserver.ts +18 -10
  17. package/dist/apis/wxml/selectorQuery.ts +26 -13
  18. package/dist/components-harmony-ets/button.ets +35 -8
  19. package/dist/components-harmony-ets/canvas.ets +51 -0
  20. package/dist/components-harmony-ets/checkbox.ets +70 -60
  21. package/dist/components-harmony-ets/form.ets +35 -16
  22. package/dist/components-harmony-ets/icon.ets +16 -8
  23. package/dist/components-harmony-ets/image.ets +22 -6
  24. package/dist/components-harmony-ets/index.ets +92 -0
  25. package/dist/components-harmony-ets/innerHtml.ets +6 -5
  26. package/dist/components-harmony-ets/input.ets +62 -40
  27. package/dist/components-harmony-ets/label.ets +44 -21
  28. package/dist/components-harmony-ets/listView.ets +31 -0
  29. package/dist/components-harmony-ets/movableArea.ets +112 -53
  30. package/dist/components-harmony-ets/movableView.ets +75 -48
  31. package/dist/components-harmony-ets/navigationBar.ets +65 -0
  32. package/dist/components-harmony-ets/pageMeta.ets +94 -0
  33. package/dist/components-harmony-ets/picker.ets +41 -38
  34. package/dist/components-harmony-ets/progress.ets +31 -24
  35. package/dist/components-harmony-ets/pseudo.ets +80 -0
  36. package/dist/components-harmony-ets/radio.ets +76 -66
  37. package/dist/components-harmony-ets/richText.ets +4 -25
  38. package/dist/components-harmony-ets/scrollList.ets +103 -0
  39. package/dist/components-harmony-ets/scrollView.ets +47 -47
  40. package/dist/components-harmony-ets/slider.ets +18 -14
  41. package/dist/components-harmony-ets/stickySection.ets +42 -0
  42. package/dist/components-harmony-ets/style.ets +386 -130
  43. package/dist/components-harmony-ets/swiper.ets +41 -4
  44. package/dist/components-harmony-ets/switch.ets +35 -31
  45. package/dist/components-harmony-ets/{index.ts → tag.ts} +6 -0
  46. package/dist/components-harmony-ets/text.ets +102 -46
  47. package/dist/components-harmony-ets/textArea.ets +49 -34
  48. package/dist/components-harmony-ets/utils/AttributeManager.ets +2 -2
  49. package/dist/components-harmony-ets/utils/DynamicCenter.ts +2 -2
  50. package/dist/components-harmony-ets/utils/flexManager.ets +49 -19
  51. package/dist/components-harmony-ets/utils/helper.ets +20 -8
  52. package/dist/components-harmony-ets/utils/htmlParser/HarmonyHTMLParser.ts +1 -2
  53. package/dist/components-harmony-ets/utils/htmlParser/index.ts +1 -1
  54. package/dist/components-harmony-ets/utils/index.ts +54 -50
  55. package/dist/components-harmony-ets/utils/styles.ets +170 -93
  56. package/dist/components-harmony-ets/video.ets +27 -19
  57. package/dist/components-harmony-ets/view.ets +47 -40
  58. package/dist/components-harmony-ets/webView.ets +6 -5
  59. package/dist/index.d.ts +152 -0
  60. package/dist/index.js +69 -43
  61. package/dist/index.js.map +1 -1
  62. package/dist/runtime-ets/bom/document.ts +6 -4
  63. package/dist/runtime-ets/bom/getComputedStyle.ts +2 -2
  64. package/dist/runtime-ets/bom/window.ts +7 -0
  65. package/dist/runtime-ets/current.ts +5 -1
  66. package/dist/runtime-ets/dom/bind.ts +28 -12
  67. package/dist/runtime-ets/dom/class-list.ts +2 -2
  68. package/dist/runtime-ets/dom/cssNesting.ts +419 -0
  69. package/dist/runtime-ets/dom/cssStyleDeclaration.ts +28 -42
  70. package/dist/runtime-ets/dom/document.ts +8 -11
  71. package/dist/runtime-ets/dom/element/canvas.ts +136 -0
  72. package/dist/runtime-ets/dom/element/element.ts +376 -56
  73. package/dist/runtime-ets/dom/element/form.ts +20 -22
  74. package/dist/runtime-ets/dom/element/index.ts +22 -2
  75. package/dist/runtime-ets/dom/element/movableArea.ts +0 -1
  76. package/dist/runtime-ets/dom/element/movableView.ts +234 -2
  77. package/dist/runtime-ets/dom/element/normal.ts +27 -6
  78. package/dist/runtime-ets/dom/element/progress.ts +0 -2
  79. package/dist/runtime-ets/dom/element/text.ts +0 -8
  80. package/dist/runtime-ets/dom/element/video.ts +4 -4
  81. package/dist/runtime-ets/dom/element/webView.ts +4 -5
  82. package/dist/runtime-ets/dom/event.ts +3 -5
  83. package/dist/runtime-ets/dom/eventTarget.ts +2 -3
  84. package/dist/runtime-ets/dom/node.ts +51 -19
  85. package/dist/runtime-ets/dom/stylesheet/covertWeb2Hm.ts +418 -237
  86. package/dist/runtime-ets/dom/stylesheet/index.ts +29 -311
  87. package/dist/runtime-ets/dom/stylesheet/type.ts +51 -9
  88. package/dist/runtime-ets/dom/stylesheet/util.ts +33 -27
  89. package/dist/runtime-ets/index.ts +2 -1
  90. package/dist/runtime-ets/interface/event.ts +1 -1
  91. package/dist/runtime-ets/utils/index.ts +74 -13
  92. package/dist/runtime-ets/utils/info.ts +2 -2
  93. package/dist/runtime-framework/react/app.ts +15 -10
  94. package/dist/runtime-framework/react/hooks.ts +0 -1
  95. package/dist/runtime-framework/react/index.ts +0 -2
  96. package/dist/runtime-framework/react/native-page.ts +185 -78
  97. package/dist/runtime-framework/react/page.ts +4 -9
  98. package/dist/runtime-framework/react/utils/index.ts +3 -3
  99. package/dist/runtime-framework/solid/app.ts +30 -46
  100. package/dist/runtime-framework/solid/connect.ts +21 -3
  101. package/dist/runtime-framework/solid/hooks.ts +16 -11
  102. package/dist/runtime-framework/solid/index.ts +6 -2
  103. package/dist/runtime-framework/solid/page.ts +85 -31
  104. package/dist/runtime-framework/solid/reconciler/props.ts +70 -25
  105. package/dist/runtime-framework/solid/reconciler/render.ts +16 -6
  106. package/dist/runtime-framework/solid/reconciler/use.ts +0 -1
  107. package/dist/runtime-framework/solid/utils/index.ts +3 -5
  108. package/dist/runtime-utils.d.ts +827 -0
  109. package/dist/runtime-utils.js +425 -253
  110. package/dist/runtime-utils.js.map +1 -1
  111. package/dist/runtime.d.ts +1 -0
  112. package/dist/runtime.js +425 -253
  113. package/dist/runtime.js.map +1 -1
  114. package/index.js +3 -1
  115. package/package.json +14 -15
  116. package/static/media/cancel.svg +1 -1
  117. package/static/media/circle.svg +1 -1
  118. package/static/media/clear.svg +1 -1
  119. package/static/media/download.svg +1 -1
  120. package/static/media/info.svg +1 -1
  121. package/static/media/info_circle.svg +1 -1
  122. package/static/media/search.svg +1 -1
  123. package/static/media/success.svg +1 -1
  124. package/static/media/success_no_circle.svg +1 -1
  125. package/static/media/warn.svg +1 -1
  126. package/types/harmony.d.ts +4 -0
  127. package/types/index.d.ts +4 -0
  128. package/types/runtime.d.ts +1 -1
  129. /package/dist/runtime-framework/solid/{contant.ts → constant.ts} +0 -0
@@ -1,26 +1,25 @@
1
1
  import { Current, document, requestAnimationFrame, TaroElement, window } from '@tarojs/runtime' // eslint-disable-line import/no-duplicates
2
- import { CONTEXT_ACTIONS, env, eventCenter, TFunc } from '@tarojs/runtime/dist/runtime.esm' // 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
3
  import { ensure, hooks, isUndefined } from '@tarojs/shared'
4
4
 
5
5
  import { ReactMeta as reactMeta } from './app'
6
6
  import { setReconciler } from './connect'
7
7
  import { ON_HIDE, ON_READY, ON_SHOW } from './constant'
8
8
  import {
9
- addLeadingSlash,
10
9
  getOnHideEventKey,
11
10
  getOnReadyEventKey,
12
- getOnShowEventKey,
11
+ getOnShowEventKey,
13
12
  getPath,
14
13
  injectPageInstance,
15
14
  removePageInstance,
16
- safeExecute
15
+ safeExecute,
17
16
  } from './page'
18
17
  import { EMPTY_OBJ, incrementId, isClassComponent } from './utils'
19
18
 
20
19
  import type { AppInstance } from '@tarojs/taro'
21
20
  import type * as React from 'react'
22
21
 
23
- const getNativeCompId = incrementId()
22
+ const getNativeCompId = incrementId(1)
24
23
  let h: typeof React.createElement
25
24
  let ReactDOM
26
25
  let nativeComponentApp: AppInstance
@@ -53,47 +52,64 @@ function initNativeComponentEntry (params: InitNativeComponentEntryParams) {
53
52
 
54
53
  componentDidMount () {
55
54
  this.ctx.component = this
56
- const rootElement = this.root.current!
57
- rootElement.ctx = this.ctx
58
- // TODO: performUpdate
59
- // rootElement.performUpdate(true)
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)
60
65
  }
61
66
 
62
67
  render () {
63
- return (
64
- h(
65
- 'view',
66
- {
67
- ref: this.root,
68
- id: this.props.compId
69
- },
70
- this.props.renderComponent(this.ctx)
71
- )
68
+ return h(
69
+ 'taro-page',
70
+ {
71
+ ref: this.root,
72
+ id: this.props.compId,
73
+ },
74
+ this.props.renderComponent(this.ctx)
72
75
  )
73
76
  }
74
77
  }
75
78
 
76
79
  class Entry extends R.Component<Record<any, any>, IEntryState> {
77
80
  state: IEntryState = {
78
- components: []
81
+ components: [],
79
82
  }
80
83
 
81
84
  componentDidMount () {
82
85
  if (isDefaultEntryDom) {
83
- Current.app = this
86
+ if (Current.app) {
87
+ Current.app = Object.assign(this, Current.app)
88
+ } else {
89
+ Current.app = this
90
+ }
84
91
  } else {
85
92
  nativeComponentApp = this
86
93
  }
87
94
  cb && cb()
88
95
  }
89
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
+
90
104
  mount (Component, compId, getCtx, cb?) {
91
105
  const isReactComponent = isClassComponent(R, Component)
92
106
  const inject = (node?: any) => node && injectPageInstance(node, compId)
93
- const refs = isReactComponent ? { ref: inject } : {
94
- forwardedRef: inject,
95
- reactReduxForwardedRef: inject
96
- }
107
+ const refs = isReactComponent
108
+ ? { ref: inject }
109
+ : {
110
+ forwardedRef: inject,
111
+ reactReduxForwardedRef: inject,
112
+ }
97
113
  if (reactMeta.PageContext === EMPTY_OBJ) {
98
114
  reactMeta.PageContext = R.createContext('')
99
115
  }
@@ -107,42 +123,49 @@ function initNativeComponentEntry (params: InitNativeComponentEntryParams) {
107
123
  return h(
108
124
  reactMeta.PageContext.Provider,
109
125
  { value: compId },
110
- h(
111
- Component,
112
- {
113
- // TODO: 传递 Props
114
- ...(ctx.props || {}),
115
- ...refs,
116
- $scope: ctx
117
- }
118
- )
126
+ h(Component, {
127
+ // TODO: 传递 Props
128
+ ...(ctx.props || {}),
129
+ ...refs,
130
+ $scope: ctx,
131
+ })
119
132
  )
120
- }
121
- })
133
+ },
134
+ }),
122
135
  }
123
- this.setState({
124
- components: [...this.state.components, item]
125
- }, () => cb && cb())
136
+
137
+ ReactDOM.flushSync(() => {
138
+ this.setState(
139
+ {
140
+ components: [...this.state.components, item],
141
+ },
142
+ () => cb && cb()
143
+ )
144
+ })
126
145
  }
127
146
 
128
147
  unmount (compId, cb?) {
129
148
  const components = this.state.components
130
- const index = components.findIndex(item => item.compId === compId)
149
+ const index = components.findIndex((item) => item.compId === compId)
131
150
  const next = [...components.slice(0, index), ...components.slice(index + 1)]
132
- this.setState({
133
- components: next
134
- }, () => {
135
- removePageInstance(compId)
136
- cb && cb()
151
+
152
+ ReactDOM.flushSync(() => {
153
+ this.setState(
154
+ {
155
+ components: next,
156
+ },
157
+ () => {
158
+ removePageInstance(compId)
159
+ cb && cb()
160
+ }
161
+ )
137
162
  })
138
163
  }
139
164
 
140
165
  render () {
141
166
  const components = this.state.components
142
167
 
143
- return (
144
- components.map(({ element }) => element)
145
- )
168
+ return components.map(({ element }) => element)
146
169
  }
147
170
  }
148
171
 
@@ -153,30 +176,44 @@ function initNativeComponentEntry (params: InitNativeComponentEntryParams) {
153
176
  // create
154
177
  const nativeApp = document.createElement('nativeComponent')
155
178
  // insert
156
- app.appendChild(nativeApp)
179
+ app?.appendChild(nativeApp)
157
180
  app = nativeApp
158
181
  }
159
- // eslint-disable-next-line react/no-deprecated
160
- ReactDOM.render(
161
- h(Entry, {}),
162
- app
163
- )
182
+
183
+ const root = ReactDOM.createRoot(app)
184
+
185
+ ReactDOM.flushSync(() => {
186
+ root.render?.(h(Entry))
187
+ })
188
+ }
189
+
190
+
191
+ const pages = new Map<string, any>()
192
+ export function setPageById (inst: any, id: string) {
193
+ pages.set(id, inst)
194
+ }
195
+
196
+ export function getPageById (id: string): any {
197
+ return pages.get(id)
164
198
  }
165
199
 
166
- export function createNativePageConfig (Component, pageName: string, react: typeof React, reactDOM: typeof ReactDOM, pageConfig) {
200
+ export function removePageById (id: string) {
201
+ pages.delete(id)
202
+ }
203
+
204
+ export function createNativePageConfig (
205
+ Component,
206
+ pageName: string,
207
+ react: typeof React,
208
+ reactDOM: typeof ReactDOM,
209
+ pageConfig
210
+ ) {
167
211
  reactMeta.R = react
168
212
  h = react.createElement
169
213
  ReactDOM = reactDOM
170
214
  setReconciler(ReactDOM)
171
- const [
172
- ONLOAD,
173
- ONUNLOAD,
174
- ONREADY,
175
- ONSHOW,
176
- ONHIDE,
177
- LIFECYCLES,
178
- SIDE_EFFECT_LIFECYCLES
179
- ] = hooks.call('getMiniLifecycleImpl')!.page
215
+ const [ONLOAD, ONUNLOAD, ONREADY, ONSHOW, ONHIDE, LIFECYCLES, SIDE_EFFECT_LIFECYCLES] =
216
+ hooks.call('getMiniLifecycleImpl')!.page
180
217
  let unmounting = false
181
218
  let prepareMountList: (() => void)[] = []
182
219
  let pageElement: TaroElement | null = null
@@ -191,7 +228,7 @@ export function createNativePageConfig (Component, pageName: string, react: type
191
228
  $taroPath: page.$taroPath,
192
229
  onReady: getOnReadyEventKey(id),
193
230
  onShow: getOnShowEventKey(id),
194
- onHide: getOnHideEventKey(id)
231
+ onHide: getOnHideEventKey(id),
195
232
  }
196
233
  if (!isUndefined(page.exitState)) {
197
234
  Current.router.exitState = page.exitState
@@ -201,12 +238,16 @@ export function createNativePageConfig (Component, pageName: string, react: type
201
238
  const pageObj: Record<string, any> = {
202
239
  options: pageConfig,
203
240
  [ONLOAD] (options: Readonly<Record<string, unknown>> = {}, cb?: TFunc) {
204
- hasLoaded = new Promise(resolve => { loadResolver = resolve })
241
+ hasLoaded = new Promise((resolve) => {
242
+ loadResolver = resolve
243
+ })
205
244
  Current.page = this as any
206
245
  this.config = pageConfig || {}
207
246
  // this.$taroPath 是页面唯一标识
208
247
  const uniqueOptions = Object.assign({}, options, { $taroTimestamp: Date.now() })
209
- const $taroPath = this.$taroPath = getPath(id, uniqueOptions)
248
+ const $taroPath = (this.$taroPath = getPath(id, uniqueOptions))
249
+
250
+ setPageById(this, $taroPath)
210
251
 
211
252
  // this.$taroParams 作为暴露给开发者的页面参数对象,可以被随意修改
212
253
  if (this.$taroParams == null) {
@@ -234,7 +275,7 @@ export function createNativePageConfig (Component, pageName: string, react: type
234
275
  ReactDOM,
235
276
  cb: () => {
236
277
  Current.app!.mount!(Component, $taroPath, () => this, mountCallback)
237
- }
278
+ },
238
279
  })
239
280
  } else {
240
281
  Current.app!.mount!(Component, $taroPath, () => this, mountCallback)
@@ -253,7 +294,11 @@ export function createNativePageConfig (Component, pageName: string, react: type
253
294
  window.trigger(CONTEXT_ACTIONS.DESTORY, $taroPath)
254
295
  // 触发onUnload生命周期
255
296
  safeExecute($taroPath, ONUNLOAD)
256
- resetCurrent()
297
+
298
+
299
+ removePageById($taroPath)
300
+
301
+ resetCurrent.call(this)
257
302
  unmounting = true
258
303
  Current.app!.unmount!($taroPath, () => {
259
304
  unmounting = false
@@ -263,7 +308,7 @@ export function createNativePageConfig (Component, pageName: string, react: type
263
308
  pageElement = null
264
309
  }
265
310
  if (prepareMountList.length) {
266
- prepareMountList.forEach(fn => fn())
311
+ prepareMountList.forEach((fn) => fn())
267
312
  prepareMountList = []
268
313
  }
269
314
  })
@@ -274,6 +319,7 @@ export function createNativePageConfig (Component, pageName: string, react: type
274
319
  safeExecute(this.$taroPath, ON_READY)
275
320
  // 通过事件触发子组件的生命周期
276
321
  requestAnimationFrame(() => eventCenter.trigger(getOnReadyEventKey(id)))
322
+ this.onReady = {}
277
323
  this.onReady.called = true
278
324
  })
279
325
  },
@@ -306,12 +352,13 @@ export function createNativePageConfig (Component, pageName: string, react: type
306
352
  }
307
353
 
308
354
  function resetCurrent () {
309
- // 小程序插件页面卸载之后返回到宿主页面时,需重置Current页面和路由。否则引发插件组件二次加载异常 fix:#11991
310
- Current.page = null
311
- Current.router = null
355
+ if (Current.page === this) {
356
+ // 小程序插件页面卸载之后返回到宿主页面时,需重置Current页面和路由。否则引发插件组件二次加载异常 fix:#11991
357
+ Current.page = null
358
+ Current.router = null
359
+ }
312
360
  }
313
361
 
314
-
315
362
  LIFECYCLES.forEach((lifecycle) => {
316
363
  pageObj[lifecycle] = function () {
317
364
  return safeExecute(this.$taroPath, lifecycle, ...arguments)
@@ -319,11 +366,8 @@ export function createNativePageConfig (Component, pageName: string, react: type
319
366
  })
320
367
 
321
368
  // onShareAppMessage 和 onShareTimeline 一样,会影响小程序右上方按钮的选项,因此不能默认注册。
322
- SIDE_EFFECT_LIFECYCLES.forEach(lifecycle => {
323
- if (Component[lifecycle] ||
324
- Component.prototype?.[lifecycle] ||
325
- Component[lifecycle.replace(/^on/, 'enable')]
326
- ) {
369
+ SIDE_EFFECT_LIFECYCLES.forEach((lifecycle) => {
370
+ if (Component[lifecycle] || Component.prototype?.[lifecycle] || Component[lifecycle.replace(/^on/, 'enable')]) {
327
371
  pageObj[lifecycle] = function (...args) {
328
372
  const target = args[0]?.target
329
373
  if (target?.id) {
@@ -342,3 +386,66 @@ export function createNativePageConfig (Component, pageName: string, react: type
342
386
 
343
387
  return pageObj
344
388
  }
389
+
390
+ export function createNativeComponentConfig (
391
+ Component,
392
+ react: typeof React,
393
+ reactdom,
394
+ componentConfig
395
+ ) {
396
+ reactMeta.R = react
397
+ h = react.createElement
398
+ ReactDOM = reactdom
399
+ setReconciler(ReactDOM)
400
+ const { isNewBlended } = componentConfig
401
+
402
+ const componentObj: Record<string, any> = {
403
+ options: componentConfig,
404
+ onLoad (
405
+ options: Readonly<Record<string, unknown>> = {}, // eslint-disable-line @typescript-eslint/no-unused-vars
406
+ cb?: TFunc
407
+ ) {
408
+ const app = isNewBlended ? nativeComponentApp : Current.app
409
+
410
+ const mountComponent = () => {
411
+ const app = isNewBlended ? nativeComponentApp : Current.app
412
+ const compId = (this.compId = getNativeCompId())
413
+
414
+ this.config = componentConfig
415
+ app!.mount!(
416
+ Component,
417
+ compId,
418
+ () => this,
419
+ () => {
420
+ const el = document.getElementById(compId)
421
+
422
+ if (!el) {
423
+ throw new Error(`没有找到组件实例。`)
424
+ } else {
425
+ el.ctx = this
426
+ cb && cb(el)
427
+ }
428
+ }
429
+ )
430
+ }
431
+
432
+ if (!app) {
433
+ initNativeComponentEntry({
434
+ R: react,
435
+ ReactDOM,
436
+ isDefaultEntryDom: !isNewBlended,
437
+ cb: mountComponent,
438
+ })
439
+ } else {
440
+ mountComponent()
441
+ }
442
+ },
443
+
444
+ onUnload () {
445
+ const app = isNewBlended ? nativeComponentApp : Current.app
446
+ app!.unmount!(this.compId)
447
+ },
448
+ }
449
+
450
+ return componentObj
451
+ }
@@ -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'
@@ -8,7 +8,7 @@ import { incrementId } from './utils'
8
8
  import type { PageConfig } from '@tarojs/taro'
9
9
 
10
10
  const instances = new Map<string, any>()
11
- const pageId = incrementId()
11
+ const pageId = incrementId(1)
12
12
 
13
13
  export function injectPageInstance (inst: any, id: string) {
14
14
  hooks.call('mergePageInstance', instances.get(id), inst)
@@ -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
 
@@ -184,6 +177,8 @@ export function createPageConfig (component: any, pageName?: string, pageConfig?
184
177
  safeExecute(this.$taroPath, ON_READY)
185
178
  // 通过事件触发子组件的生命周期
186
179
  requestAnimationFrame(() => eventCenter.trigger(getOnReadyEventKey(id)))
180
+ this.onReady = {}
181
+ this.onReady.called = true
187
182
  })
188
183
  },
189
184
  [ONSHOW] (options = {}) {
@@ -7,9 +7,9 @@ export function capitalize (s: string) {
7
7
  return s.charAt(0).toUpperCase() + s.slice(1)
8
8
  }
9
9
 
10
- export const incrementId = () => {
11
- let n = 0
12
- return () => (n++).toString()
10
+ export const incrementId = (init = 0) => {
11
+ let n = init
12
+ return () => n++
13
13
  }
14
14
 
15
15
  export function ensureIsArray<T> (item: T | T[]): T[] {
@@ -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-solid/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,13 +31,10 @@ 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 = config?.appId || 'app'
39
35
 
40
36
  if (ReactMeta.Container === EMPTY_OBJ) {
41
- const Container = document.createElement('view')
37
+ const Container = document.getElementById(appId)
42
38
 
43
39
  Container.id = appId
44
40
  ReactMeta.Container = Container
@@ -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,33 @@ 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(
72
+ 'taro-page',
73
+ { id, className: 'taro_page' },
74
+ children
75
+ )
79
76
  },
80
77
  }),
81
78
  })
82
79
  }
83
80
 
84
- if (!isWeb) {
85
- renderReactRoot()
86
- }
87
-
88
- const [ONLAUNCH, ONSHOW, ONHIDE] = hooks.call('getMiniLifecycleImpl')!.app
81
+ renderReactRoot()
89
82
 
90
- const appObj: AppInstance = Object.create(
83
+ const app: AppInstance = Object.create(
91
84
  {
92
- mount(component: Component, id: string, cb: () => void) {
85
+ mount(component: SolidComponent, id: string, cb: () => void) {
93
86
  setPages((old) => [
94
87
  ...old,
95
88
  { id, component },
96
89
  ])
97
90
  batch(cb)
98
91
  },
99
-
100
92
  unmount(id: string, cb: () => void) {
101
- setPages(
102
- pages().filter((item) => {
103
- return item.id !== id
104
- })
105
- )
93
+ const idx = elements().findIndex((item) => item.id === id)
94
+ setElements((old) => {
95
+ old.splice(idx, 1)
96
+ return old
97
+ })
106
98
  batch(cb)
107
99
  },
108
100
  },
@@ -112,15 +104,10 @@ export function createSolidApp(App: Component, config: AppConfig) {
112
104
  value: config,
113
105
  }),
114
106
 
115
- [ONLAUNCH]: setDefaultDescriptor({
107
+ onLaunch: setDefaultDescriptor({
116
108
  value(options) {
117
109
  setRouterParams(options)
118
110
 
119
- if (isWeb) {
120
- // 由于 H5 路由初始化的时候会清除 app 下的 dom 元素,所以需要在路由初始化后执行 render
121
- renderReactRoot()
122
- }
123
-
124
111
  const onLaunch = () => {
125
112
  const app = getAppInstance()
126
113
 
@@ -151,28 +138,25 @@ export function createSolidApp(App: Component, config: AppConfig) {
151
138
 
152
139
  onLaunch()
153
140
  triggerAppHook('onLaunch', options)
141
+ eventCenter.trigger('__taroRouterLaunch', options)
154
142
  },
155
143
  }),
156
-
157
- [ONSHOW]: setDefaultDescriptor({
144
+ onShow: setDefaultDescriptor({
158
145
  value(options) {
159
146
  setRouterParams(options)
160
147
  triggerAppHook('onShow', options)
161
148
  },
162
149
  }),
163
-
164
- [ONHIDE]: setDefaultDescriptor({
150
+ onHide: setDefaultDescriptor({
165
151
  value() {
166
152
  triggerAppHook('onHide')
167
153
  },
168
154
  }),
169
-
170
155
  onError: setDefaultDescriptor({
171
156
  value(error: string) {
172
157
  triggerAppHook('onError', error)
173
158
  },
174
159
  }),
175
-
176
160
  onPageNotFound: setDefaultDescriptor({
177
161
  value(res: unknown) {
178
162
  triggerAppHook('onPageNotFound', res)
@@ -195,6 +179,6 @@ export function createSolidApp(App: Component, config: AppConfig) {
195
179
  }
196
180
  }
197
181
 
198
- Current.app = appObj
199
- return appObj
182
+ Current.app = app
183
+ return app
200
184
  }
@@ -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
  }