@tarojs/plugin-platform-harmony-ets 4.0.0-beta.21 → 4.0.0-beta.23

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 (68) hide show
  1. package/dist/apis/base/system.ts +1 -1
  2. package/dist/apis/canvas/index.ts +10 -1
  3. package/dist/apis/index.ts +24 -11
  4. package/dist/apis/ui/animation/animation.ts +2 -1
  5. package/dist/apis/wxml/IntersectionObserver.ts +5 -1
  6. package/dist/components-harmony-ets/button.ets +8 -1
  7. package/dist/components-harmony-ets/canvas.ets +51 -0
  8. package/dist/components-harmony-ets/checkbox.ets +7 -3
  9. package/dist/components-harmony-ets/form.ets +10 -2
  10. package/dist/components-harmony-ets/icon.ets +8 -1
  11. package/dist/components-harmony-ets/image.ets +8 -1
  12. package/dist/components-harmony-ets/index.ets +53 -0
  13. package/dist/components-harmony-ets/input.ets +2 -1
  14. package/dist/components-harmony-ets/label.ets +9 -2
  15. package/dist/components-harmony-ets/movableArea.ets +10 -3
  16. package/dist/components-harmony-ets/movableView.ets +10 -3
  17. package/dist/components-harmony-ets/picker.ets +1 -1
  18. package/dist/components-harmony-ets/progress.ets +8 -1
  19. package/dist/components-harmony-ets/radio.ets +7 -3
  20. package/dist/components-harmony-ets/scrollView.ets +9 -2
  21. package/dist/components-harmony-ets/slider.ets +2 -1
  22. package/dist/components-harmony-ets/style.ets +40 -4
  23. package/dist/components-harmony-ets/swiper.ets +8 -1
  24. package/dist/components-harmony-ets/switch.ets +3 -1
  25. package/dist/components-harmony-ets/text.ets +8 -1
  26. package/dist/components-harmony-ets/textArea.ets +2 -1
  27. package/dist/components-harmony-ets/utils/flexManager.ets +2 -2
  28. package/dist/components-harmony-ets/utils/helper.ets +1 -3
  29. package/dist/components-harmony-ets/utils/htmlParser/index.ts +1 -1
  30. package/dist/components-harmony-ets/utils/index.ts +8 -62
  31. package/dist/components-harmony-ets/video.ets +9 -2
  32. package/dist/components-harmony-ets/view.ets +9 -2
  33. package/dist/index.d.ts +1 -1
  34. package/dist/runtime-ets/bom/window.ts +5 -0
  35. package/dist/runtime-ets/current.ts +1 -0
  36. package/dist/runtime-ets/dom/bind.ts +3 -3
  37. package/dist/runtime-ets/dom/cssNesting.ts +104 -22
  38. package/dist/runtime-ets/dom/cssStyleDeclaration.ts +2 -5
  39. package/dist/runtime-ets/dom/element/canvas.ts +136 -0
  40. package/dist/runtime-ets/dom/element/element.ts +59 -44
  41. package/dist/runtime-ets/dom/element/form.ts +4 -14
  42. package/dist/runtime-ets/dom/element/index.ts +4 -2
  43. package/dist/runtime-ets/dom/element/progress.ts +0 -1
  44. package/dist/runtime-ets/dom/element/text.ts +0 -8
  45. package/dist/runtime-ets/dom/element/video.ts +4 -3
  46. package/dist/runtime-ets/dom/node.ts +15 -14
  47. package/dist/runtime-ets/dom/stylesheet/covertWeb2Hm.ts +5 -4
  48. package/dist/runtime-ets/dom/stylesheet/util.ts +12 -10
  49. package/dist/runtime-ets/utils/index.ts +20 -2
  50. package/dist/runtime-ets/utils/info.ts +1 -1
  51. package/dist/runtime-framework/react/app.ts +2 -1
  52. package/dist/runtime-framework/react/native-page.ts +3 -2
  53. package/dist/runtime-framework/react/page.ts +1 -0
  54. package/dist/runtime-framework/solid/app.ts +19 -39
  55. package/dist/runtime-framework/solid/connect.ts +20 -2
  56. package/dist/runtime-framework/solid/hooks.ts +16 -11
  57. package/dist/runtime-framework/solid/index.ts +7 -1
  58. package/dist/runtime-framework/solid/page.ts +84 -23
  59. package/dist/runtime-framework/solid/reconciler/props.ts +65 -20
  60. package/dist/runtime-framework/solid/reconciler/render.ts +2 -1
  61. package/dist/runtime-utils.d.ts +3 -1
  62. package/dist/runtime-utils.js +24 -12
  63. package/dist/runtime-utils.js.map +1 -1
  64. package/dist/runtime.js +24 -12
  65. package/dist/runtime.js.map +1 -1
  66. package/package.json +10 -10
  67. /package/dist/components-harmony-ets/{index.ts → tag.ts} +0 -0
  68. /package/dist/runtime-framework/solid/{contant.ts → constant.ts} +0 -0
@@ -42,13 +42,27 @@ export function convertNumber2VP (value: number, unit = 'px') {
42
42
  if (unit === 'vw' || unit === 'vh') {
43
43
  return (value / 100 * (unit === 'vw' ? display.width: display.height)) + 'px'
44
44
  }
45
+ if (unit === 'PX') {
46
+ // 特殊单位:相当于PX、pX、Px
47
+ return pxTransformHelper(value, 'PX')
48
+ }
45
49
  return pxTransformHelper(value, 'vp')
46
50
  }
47
51
 
52
+ export function parseClasses (classNames: string | string[] = []): string[] {
53
+ if (typeof classNames === 'string') {
54
+ return classNames.includes(' ') ? classNames.split(' ') : [classNames]
55
+ } else if (Array.isArray(classNames)) {
56
+ return classNames // Note: 不考虑支持单个元素传入多个类名的情况,过于损耗性能
57
+ }
58
+
59
+ return []
60
+ }
61
+
48
62
  // 合并静态样式,从样式表里面找到对应的样式
49
- export function calcStaticStyle (styleSheet: Record<string, CSSProperties>, classNames: string, style: CSSProperties): CSSProperties {
63
+ export function calcStaticStyle (styleSheet: Record<string, CSSProperties>, classNames: string | string[] = [], style: CSSProperties): CSSProperties {
50
64
  const obj: CSSProperties[] = []
51
- const classes = typeof classNames === 'string' ? classNames.split(' ') : []
65
+ const classes = parseClasses(classNames)
52
66
  if (classes.length === 1) {
53
67
  if (style) {
54
68
  return Object.assign({}, styleSheet[classNames], style)
@@ -92,6 +106,10 @@ export function getPageScrollerOrNode (scrollerOrNode: any, page: any) {
92
106
  return scrollerOrNode
93
107
  }
94
108
 
109
+ export function ObjectKeys(obj: object): string[] {
110
+ return Object.keys(obj)
111
+ }
112
+
95
113
  export function ObjectAssign(...objects) {
96
114
  return Object.assign.apply(this, [{}].concat(...objects))
97
115
  }
@@ -50,7 +50,7 @@ function tapCallbackToNodeAndUpdate (node: TaroElement, eventName: string, callb
50
50
  callback && callback(...eventResult)
51
51
  }
52
52
 
53
- if (!node._isDynamicNode || !node._isCompileMode) {
53
+ if (!node._isDynamicNode && node._isCompileMode) {
54
54
  node.updateComponent()
55
55
  }
56
56
  }
@@ -1,10 +1,11 @@
1
1
  import { Current, document } from '@tarojs/runtime' // eslint-disable-line import/no-duplicates
2
- import { AppInstance, eventCenter } from '@tarojs/runtime/dist/runtime.esm' // eslint-disable-line import/no-duplicates
2
+ import { eventCenter } from '@tarojs/runtime/dist/runtime.esm' // eslint-disable-line import/no-duplicates
3
3
 
4
4
  import { setReconciler } from './connect'
5
5
  import { injectPageInstance } from './page'
6
6
  import { EMPTY_OBJ, incrementId, isClassComponent } from './utils'
7
7
 
8
+ import type { AppInstance } from '@tarojs/runtime'
8
9
  import type React from 'react'
9
10
 
10
11
  let h: typeof React.createElement
@@ -9,7 +9,7 @@ import {
9
9
  addLeadingSlash,
10
10
  getOnHideEventKey,
11
11
  getOnReadyEventKey,
12
- getOnShowEventKey,
12
+ getOnShowEventKey,
13
13
  getPath,
14
14
  injectPageInstance,
15
15
  removePageInstance,
@@ -157,7 +157,7 @@ function initNativeComponentEntry (params: InitNativeComponentEntryParams) {
157
157
  // create
158
158
  const nativeApp = document.createElement('nativeComponent')
159
159
  // insert
160
- app.appendChild(nativeApp)
160
+ app?.appendChild(nativeApp)
161
161
  app = nativeApp
162
162
  }
163
163
  // eslint-disable-next-line react/no-deprecated
@@ -278,6 +278,7 @@ export function createNativePageConfig (Component, pageName: string, react: type
278
278
  safeExecute(this.$taroPath, ON_READY)
279
279
  // 通过事件触发子组件的生命周期
280
280
  requestAnimationFrame(() => eventCenter.trigger(getOnReadyEventKey(id)))
281
+ this.onReady = {}
281
282
  this.onReady.called = true
282
283
  })
283
284
  },
@@ -184,6 +184,7 @@ export function createPageConfig (component: any, pageName?: string, pageConfig?
184
184
  safeExecute(this.$taroPath, ON_READY)
185
185
  // 通过事件触发子组件的生命周期
186
186
  requestAnimationFrame(() => eventCenter.trigger(getOnReadyEventKey(id)))
187
+ this.onReady = {}
187
188
  this.onReady.called = true
188
189
  })
189
190
  },
@@ -1,5 +1,6 @@
1
- import { Current, document } from '@tarojs/runtime'
2
- import { hooks, isWebPlatform } from '@tarojs/shared'
1
+ import { Current, document } from '@tarojs/runtime' // eslint-disable-line import/no-duplicates
2
+ import { eventCenter } from '@tarojs/runtime/dist/runtime.esm' // eslint-disable-line import/no-duplicates
3
+ import { hooks } from '@tarojs/shared'
3
4
  import { batch, createContext, createRoot, createSignal, For } from 'solid-js'
4
5
 
5
6
  import { setReconciler } from './connect'
@@ -11,8 +12,6 @@ import type { AppInstance, Instance, PageLifeCycle, PageProps, ReactAppInstance
11
12
  import type { AppConfig } from '@tarojs/taro'
12
13
  import type { Component } from './connect'
13
14
 
14
- const isWeb = isWebPlatform()
15
-
16
15
  export const ReactMeta = {
17
16
  R: EMPTY_OBJ,
18
17
  Container: 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,6 +44,7 @@ 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
@@ -71,23 +68,15 @@ 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
81
  mount(component: Component, id: string, cb: () => void) {
93
82
  setPages((old) => [
@@ -96,13 +85,12 @@ export function createSolidApp(App: Component, config: AppConfig) {
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
 
4
+ import { ensureIsArray } from './utils'
5
+
6
+ import type { TaroNode } from '@tarojs/runtime'
7
+
5
8
  export type Component = (props?: any) => TaroNode
6
9
 
7
- export function setReconciler() {
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
  }
@@ -1,9 +1,4 @@
1
- import {
2
- AppInstance,
3
- Current,
4
- PageLifeCycle,
5
- TFunc
6
- } from '@tarojs/runtime'
1
+ import { Current } from '@tarojs/runtime'
7
2
  import { isArray, isFunction } from '@tarojs/shared'
8
3
  import {
9
4
  createMemo,
@@ -15,6 +10,12 @@ import { ReactMeta } from './app'
15
10
  import { getPageInstance, injectPageInstance } from './page'
16
11
  import { HOOKS_APP_ID } from './utils'
17
12
 
13
+ import type {
14
+ AppInstance,
15
+ PageLifeCycle,
16
+ TFunc
17
+ } from '@tarojs/runtime/dist/runtime.esm'
18
+
18
19
  const createTaroHook = (lifecycle: keyof PageLifeCycle | keyof AppInstance) => {
19
20
  return (fn: TFunc) => {
20
21
  const id = ReactMeta.PageContext || HOOKS_APP_ID
@@ -30,10 +31,13 @@ const createTaroHook = (lifecycle: keyof PageLifeCycle | keyof AppInstance) => {
30
31
  })
31
32
  }
32
33
 
33
- if (isFunction(inst![lifecycle])) {
34
- inst![lifecycle] = [inst?.[lifecycle], fn]
34
+ if (isFunction(inst[lifecycle])) {
35
+ inst[lifecycle] = [inst[lifecycle], fn]
35
36
  } else {
36
- inst![lifecycle] = [...(inst![lifecycle] || []), fn]
37
+ inst[lifecycle] = [
38
+ ...((inst[lifecycle]) || []),
39
+ fn
40
+ ]
37
41
  }
38
42
 
39
43
  if (first) {
@@ -43,9 +47,9 @@ const createTaroHook = (lifecycle: keyof PageLifeCycle | keyof AppInstance) => {
43
47
  onCleanup(() => {
44
48
  const list = inst![lifecycle]
45
49
  if (list === fn) {
46
- inst![lifecycle] = undefined
50
+ (inst[lifecycle]) = undefined
47
51
  } else if (isArray(list)) {
48
- inst![lifecycle] = list.filter((item) => item !== fn)
52
+ (inst[lifecycle]) = list.filter(item => item !== fn)
49
53
  }
50
54
  })
51
55
  })
@@ -58,6 +62,7 @@ export const useDidShow = createTaroHook('componentDidShow')
58
62
 
59
63
  /** App */
60
64
  export const useError = createTaroHook('onError')
65
+ export const useUnhandledRejection = createTaroHook('onUnhandledRejection')
61
66
  export const useLaunch = createTaroHook('onLaunch')
62
67
  export const usePageNotFound = createTaroHook('onPageNotFound')
63
68
 
@@ -1,8 +1,14 @@
1
1
  import { hooks } from '@tarojs/shared'
2
2
 
3
+ import * as taroHooks from './hooks'
4
+
3
5
  // declare const __TARO_FRAMEWORK__: string;
4
6
 
5
- hooks.tap('initNativeApi', function (_taro) {})
7
+ hooks.tap('initNativeApi', function (taro) {
8
+ for (const hook in taroHooks) {
9
+ taro[hook] = taroHooks[hook]
10
+ }
11
+ })
6
12
 
7
13
  export * from './app'
8
14
  export * from './connect'
@@ -1,13 +1,17 @@
1
- import { Current } from '@tarojs/runtime'
2
- import { isArray, isFunction, isUndefined } from '@tarojs/shared'
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
3
+ import { hooks, isArray, isFunction, isUndefined } from '@tarojs/shared'
3
4
 
4
- import { ON_HIDE, ON_LOAD, ON_READY, ON_SHOW, ON_UNLOAD } from './contant'
5
+ import { ON_HIDE, ON_LOAD, ON_READY, ON_SHOW, ON_UNLOAD } from './constant'
5
6
  import { incrementId } from './utils'
6
7
 
8
+ import type { PageConfig } from '@tarojs/taro'
9
+
7
10
  const instances = new Map<string, any>()
8
11
  const pageId = incrementId()
9
12
 
10
13
  export function injectPageInstance (inst: any, id: string) {
14
+ hooks.call('mergePageInstance', instances.get(id), inst)
11
15
  instances.set(id, inst)
12
16
  }
13
17
 
@@ -33,6 +37,7 @@ export function safeExecute (path: string, lifecycle: string, ...args: unknown[]
33
37
  return
34
38
  }
35
39
 
40
+ lifecycle = lifecycle.replace(/^on(Show|Hide)$/, 'componentDid$1')
36
41
  const func = instance[lifecycle]
37
42
 
38
43
  if (isArray(func)) {
@@ -75,9 +80,19 @@ export function getOnHideEventKey (path: string) {
75
80
  return path + '.' + ON_HIDE
76
81
  }
77
82
 
78
- export function createPageConfig (component: any, pageName?: string) {
83
+ export function createPageConfig (component: any, pageName?: string, pageConfig?: PageConfig) {
79
84
  // 小程序 Page 构造器是一个傲娇小公主,不能把复杂的对象挂载到参数上
80
85
  const id = pageName ?? `taro_page_${pageId()}`
86
+ const [
87
+ ONLOAD,
88
+ ONUNLOAD,
89
+ ONREADY,
90
+ ONSHOW,
91
+ ONHIDE,
92
+ LIFECYCLES,
93
+ SIDE_EFFECT_LIFECYCLES,
94
+ ] = hooks.call('getMiniLifecycleImpl')!.page
95
+
81
96
  let pageElement: any = null
82
97
  let unmounting = false
83
98
  let prepareMountList: (() => void)[] = []
@@ -102,7 +117,7 @@ export function createPageConfig (component: any, pageName?: string) {
102
117
  let loadResolver: (...args: any[]) => void
103
118
  let hasLoaded: Promise<void>
104
119
  const page = {
105
- onLoad (options: Readonly<Record<string, unknown>> = {}, cb?: (...args: any[]) => any) {
120
+ [ONLOAD] (options: Readonly<Record<string, unknown>> = {}, cb?: (...args: any[]) => any) {
106
121
  hasLoaded = new Promise(resolve => { loadResolver = resolve })
107
122
 
108
123
  Current.page = this as any
@@ -118,21 +133,21 @@ export function createPageConfig (component: any, pageName?: string) {
118
133
 
119
134
  setCurrentRouter(this)
120
135
 
121
- // window.trigger(CONTEXT_ACTIONS.INIT, $taroPath)
136
+ window.trigger(CONTEXT_ACTIONS.INIT, $taroPath)
122
137
 
123
138
  const mount = () => {
139
+ // @ts-ignore
124
140
  Current.app!.mount!(component, $taroPath, () => {
125
- // pageElement = document.getElementById($taroPath)
141
+ pageElement = document.getElementById($taroPath)
126
142
 
127
- // if (!pageElement) {
128
- // throw new Error(`没有找到页面实例。`)
129
- // }
143
+ if (!pageElement) {
144
+ throw new Error(`没有找到页面实例。`)
145
+ }
130
146
 
131
147
  safeExecute($taroPath, ON_LOAD, this.$taroParams)
132
148
  loadResolver()
133
- cb && cb()
134
- // pageElement.ctx = this
135
- // pageElement.performUpdate(true, cb)
149
+ cb && cb(pageElement)
150
+ pageElement.ctx = this
136
151
  })
137
152
  }
138
153
 
@@ -142,10 +157,10 @@ export function createPageConfig (component: any, pageName?: string) {
142
157
  mount()
143
158
  }
144
159
  },
145
- onUnLoad () {
160
+ [ONUNLOAD] () {
146
161
  const $taroPath = this.$taroPath
147
162
  // 销毁当前页面的上下文信息
148
- // window.trigger(CONTEXT_ACTIONS.DESTORY, $taroPath)
163
+ window.trigger(CONTEXT_ACTIONS.DESTORY, $taroPath)
149
164
 
150
165
  // 触发onUnload生命周期
151
166
  safeExecute($taroPath, ON_UNLOAD)
@@ -163,22 +178,31 @@ export function createPageConfig (component: any, pageName?: string) {
163
178
  }
164
179
  })
165
180
  },
166
- onShow (options = {}) {
181
+ [ONREADY] () {
182
+ hasLoaded.then(() => {
183
+ // 触发生命周期
184
+ safeExecute(this.$taroPath, ON_READY)
185
+ // 通过事件触发子组件的生命周期
186
+ requestAnimationFrame(() => eventCenter.trigger(getOnReadyEventKey(id)))
187
+ this.onReady.called = true
188
+ })
189
+ },
190
+ [ONSHOW] (options = {}) {
167
191
  hasLoaded.then(() => {
168
192
  // 设置 Current 的 page 和 router
169
193
  Current.page = this as any
170
194
  setCurrentRouter(this)
171
195
  // 恢复上下文信息
172
- // window.trigger(CONTEXT_ACTIONS.RECOVER, this.$taroPath)
196
+ window.trigger(CONTEXT_ACTIONS.RECOVER, this.$taroPath)
173
197
  // 触发生命周期
174
198
  safeExecute(this.$taroPath, ON_SHOW, options)
175
- // TODO 通过事件触发子组件的生命周期
176
- // raf(() => eventCenter.trigger(getOnShowEventKey(id)))
199
+ // 通过事件触发子组件的生命周期
200
+ requestAnimationFrame(() => eventCenter.trigger(getOnShowEventKey(id)))
177
201
  })
178
202
  },
179
- onHide () {
203
+ [ONHIDE] () {
180
204
  // 缓存当前页面上下文信息
181
- // window.trigger(CONTEXT_ACTIONS.RESTORE, this.$taroPath)
205
+ window.trigger(CONTEXT_ACTIONS.RESTORE, this.$taroPath)
182
206
 
183
207
  // 设置 Current 的 page 和 router
184
208
  if (Current.page === this) {
@@ -188,9 +212,46 @@ export function createPageConfig (component: any, pageName?: string) {
188
212
  // 触发生命周期
189
213
  safeExecute(this.$taroPath, ON_HIDE)
190
214
  // TODO 通过事件触发子组件的生命周期
191
- // eventCenter.trigger(getOnHideEventKey(id))
192
- }
215
+ eventCenter.trigger(getOnHideEventKey(id))
216
+ },
193
217
  }
194
218
 
219
+ LIFECYCLES.forEach((lifecycle) => {
220
+ let isDefer = false
221
+ lifecycle = lifecycle.replace(/^defer:/, () => {
222
+ isDefer = true
223
+ return ''
224
+ })
225
+ page[lifecycle] = function () {
226
+ const exec = () => safeExecute(this.$taroPath, lifecycle, ...arguments)
227
+ if (isDefer) {
228
+ hasLoaded.then(exec)
229
+ } else {
230
+ return exec()
231
+ }
232
+ }
233
+ })
234
+
235
+ // onShareAppMessage 和 onShareTimeline 一样,会影响小程序右上方按钮的选项,因此不能默认注册。
236
+ SIDE_EFFECT_LIFECYCLES.forEach(lifecycle => {
237
+ if (component[lifecycle] ||
238
+ component.prototype?.[lifecycle] ||
239
+ component[lifecycle.replace(/^on/, 'enable')] ||
240
+ pageConfig?.[lifecycle.replace(/^on/, 'enable')]
241
+ ) {
242
+ page[lifecycle] = function (...args) {
243
+ const target = args[0]?.target as any
244
+ if (target?.id) {
245
+ const id = target.id
246
+ const element = env.document.getElementById(id)
247
+ if (element) {
248
+ target.dataset = element.dataset
249
+ }
250
+ }
251
+ return safeExecute(this.$taroPath, lifecycle, ...args)
252
+ }
253
+ }
254
+ })
255
+
195
256
  return page
196
257
  }
@@ -5,11 +5,16 @@ import type { Style, TaroElement } from '@tarojs/runtime'
5
5
 
6
6
  export type Props = Record<string, unknown>
7
7
 
8
+ const isHarmony = process.env.TARO_PLATFORM === 'harmony'
9
+ const IS_NON_DIMENSIONAL = /max|aspect|acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i
10
+
8
11
  function isEventName (s: string) {
9
12
  return s[0] === 'o' && s[1] === 'n'
10
13
  }
11
14
 
12
- const IS_NON_DIMENSIONAL = /max|aspect|acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i
15
+ function isEqual (obj1, obj2) {
16
+ return JSON.stringify(obj1) === JSON.stringify(obj2)
17
+ }
13
18
 
14
19
  export function updateProps (dom: TaroElement, oldProps: Props, newProps: Props) {
15
20
  const updatePayload = getUpdatePayload(dom, oldProps, newProps)
@@ -59,12 +64,11 @@ function setEvent (dom: TaroElement, name: string, value: unknown, oldValue?: un
59
64
 
60
65
  const compName = capitalize(toCamelCase(dom.tagName.toLowerCase()))
61
66
 
62
- if (eventName === 'click' && compName in internalComponents) {
67
+ if (eventName === 'click' && !isHarmony && compName in internalComponents) {
63
68
  eventName = 'tap'
64
69
  }
65
70
 
66
71
  if (isFunction(value)) {
67
- const isHarmony = process.env.TARO_PLATFORM === 'harmony'
68
72
  if (oldValue) {
69
73
  dom.removeEventListener(eventName, oldValue as any, !isHarmony ? false : undefined)
70
74
  dom.addEventListener(eventName, value, !isHarmony ? { isCapture, sideEffect: false } : undefined)
@@ -76,19 +80,24 @@ function setEvent (dom: TaroElement, name: string, value: unknown, oldValue?: un
76
80
  }
77
81
  }
78
82
 
79
- function setStyle (style: Style, key: string, value: string | number) {
80
- if (key[0] === '-') {
81
- style.setProperty(key, value.toString())
83
+ function setStyle (style: Style, key: string, value: unknown) {
84
+ if (key[0] === '-' && !isHarmony) {
82
85
  // css variables need not further judgment
86
+ style.setProperty(key, (value as string).toString())
83
87
  return
84
88
  }
85
89
 
86
- style[key] =
87
- isNumber(value) && IS_NON_DIMENSIONAL.test(key) === false
88
- ? convertNumber2PX(value)
89
- : value == null
90
- ? ''
91
- : value
90
+ if (isHarmony && key.startsWith('_')) {
91
+ // harmony样式已处理
92
+ style[key] = value == null ? '' : value
93
+ } else {
94
+ style[key] =
95
+ isNumber(value) && IS_NON_DIMENSIONAL.test(key) === false
96
+ ? convertNumber2PX(value)
97
+ : value == null
98
+ ? ''
99
+ : value
100
+ }
92
101
  }
93
102
 
94
103
  type StyleValue = Record<string, string | number>
@@ -99,13 +108,9 @@ interface DangerouslySetInnerHTML {
99
108
  export function setProperty (dom: TaroElement, name: string, value: unknown, oldValue?: unknown) {
100
109
  name = name === 'className' ? 'class' : name
101
110
 
102
- if (
103
- name === 'key' ||
104
- name === 'children' ||
105
- name === 'ref'
106
- ) {
107
- // skip
108
- } else if (name === 'style') {
111
+ if (['key', 'children', 'ref'].includes(name)) return
112
+
113
+ if (name === 'style') {
109
114
  const style = dom.style
110
115
  if (isString(value)) {
111
116
  style.cssText = value
@@ -118,6 +123,7 @@ export function setProperty (dom: TaroElement, name: string, value: unknown, old
118
123
  if (isObject<StyleValue>(oldValue)) {
119
124
  for (const i in oldValue) {
120
125
  if (!(value && i in (value as StyleValue))) {
126
+ // harmony设置style,路径设置路径如下:dom.style => cssStyleDeclaration.setProperty => convertWebStyle2HmStyle => dom._st.hmStyle
121
127
  setStyle(style, i, '')
122
128
  }
123
129
  }
@@ -125,12 +131,40 @@ export function setProperty (dom: TaroElement, name: string, value: unknown, old
125
131
 
126
132
  if (isObject<StyleValue>(value)) {
127
133
  for (const i in value) {
128
- if (!oldValue || value[i] !== (oldValue as StyleValue)[i]) {
134
+ if (!oldValue || !isEqual(value[i], (oldValue as StyleValue)[i])) {
129
135
  setStyle(style, i, value[i])
130
136
  }
131
137
  }
132
138
  }
133
139
  }
140
+ } else if (name === '__hmStyle') {
141
+ // 鸿蒙样式特殊处理
142
+ // @ts-ignore
143
+ const style = dom._st.hmStyle // __hmStyle是已经被处理过的鸿蒙样式,可以直接塞进hmStyle对象内
144
+ if (isObject<StyleValue>(oldValue)) {
145
+ for (const i in oldValue) {
146
+ if (!(value && i in (value as StyleValue))) {
147
+ // 鸿蒙伪类特殊处理
148
+ if (isHarmony && (i === '::after' || i === '::before')) {
149
+ setPseudo(dom, i, null)
150
+ } else {
151
+ style[i] = ''
152
+ }
153
+ }
154
+ }
155
+ }
156
+ if (isObject<StyleValue>(value)) {
157
+ for (const i in value) {
158
+ if (!oldValue || !isEqual(value[i], (oldValue as StyleValue)[i])) {
159
+ // 鸿蒙伪类特殊处理
160
+ if (isHarmony && (i === '::after' || i === '::before')) {
161
+ setPseudo(dom, i, value[i] as unknown as StyleValue)
162
+ } else {
163
+ style[i] = value[i]
164
+ }
165
+ }
166
+ }
167
+ }
134
168
  } else if (isEventName(name)) {
135
169
  setEvent(dom, name, value, oldValue)
136
170
  } else if (name === 'dangerouslySetInnerHTML') {
@@ -149,3 +183,14 @@ export function setProperty (dom: TaroElement, name: string, value: unknown, old
149
183
  }
150
184
  }
151
185
  }
186
+
187
+ // 设置鸿蒙伪类属性(特殊设置)
188
+ function setPseudo(dom: TaroElement, name: '::after' | '::before', value: StyleValue | null){
189
+ if (name === '::after') {
190
+ // @ts-ignore
191
+ dom.set_pseudo_after(value)
192
+ } else if (name === '::before') {
193
+ // @ts-ignore
194
+ dom.set_pseudo_before(value)
195
+ }
196
+ }