@mpxjs/core 2.8.39 → 2.8.40-test.2

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/@types/index.d.ts CHANGED
@@ -24,25 +24,37 @@ type UnionToIntersection<U> = (U extends any
24
24
  ? (k: U) => void
25
25
  : never) extends ((k: infer I) => void)
26
26
  ? I
27
- : never;
27
+ : never
28
28
 
29
- type ArrayType<T extends any[]> = T extends Array<infer R> ? R : never;
29
+ type ArrayType<T extends any[]> = T extends Array<infer R> ? R : never
30
30
 
31
31
  // Mpx types
32
32
  type Data = object | (() => object)
33
33
 
34
- type PropType = StringConstructor | NumberConstructor | BooleanConstructor | ObjectConstructor | ArrayConstructor | null
35
-
36
- interface PropOpt {
37
- type: PropType
38
- optionalTypes?: Array<PropType>
39
- value?: any
40
-
41
- observer? (value: any, old: any, changedPath: string): void
34
+ export type PropType<T> = {
35
+ __type: T
36
+ } & (
37
+ T extends String
38
+ ? StringConstructor
39
+ : T extends number
40
+ ? NumberConstructor
41
+ : T extends boolean
42
+ ? BooleanConstructor
43
+ : T extends any[]
44
+ ? ArrayConstructor
45
+ : T extends object
46
+ ? ObjectConstructor
47
+ : never
48
+ )
49
+
50
+ type FullPropType<T> = {
51
+ type: PropType<T>
52
+ value?: T
53
+ optionalTypes?: WechatMiniprogram.Component.ShortProperty[]
42
54
  }
43
55
 
44
56
  interface Properties {
45
- [key: string]: PropType | PropOpt
57
+ [key: string]: WechatMiniprogram.Component.AllProperty
46
58
  }
47
59
 
48
60
  interface Methods {
@@ -71,23 +83,17 @@ interface WatchField {
71
83
 
72
84
  type GetDataType<T> = T extends () => any ? ReturnType<T> : T
73
85
 
74
- type PropValueType<Def> = Def extends {
75
- type: (...args: any[]) => infer T;
76
- optionalType?: ((...args: any[]) => infer T)[];
77
- value?: infer T;
78
- }
79
- ? T
80
- : Def extends (...args: any[]) => infer T
81
- ? T
82
- : any;
83
-
84
- type GetPropsType<T> = {
85
- readonly [K in keyof T]: PropValueType<T[K]>
86
+ type GetPropsType<T extends Properties> = {
87
+ readonly [K in keyof T]: T[K] extends FullPropType<infer V>
88
+ ? V
89
+ : T[K] extends PropType<infer V>
90
+ ? V
91
+ : WechatMiniprogram.Component.PropertyToData<T[K]>
86
92
  }
87
93
 
88
94
  type RequiredPropertyNames<T> = {
89
95
  [K in keyof T]-?: T[K] extends undefined ? never : K
90
- }[keyof T];
96
+ }[keyof T]
91
97
 
92
98
  type RequiredPropertiesForUnion<T> = T extends object ? Pick<T, RequiredPropertyNames<T>> : never
93
99
 
@@ -96,6 +102,7 @@ interface Mixin<D, P, C, M> {
96
102
  properties?: P
97
103
  computed?: C
98
104
  methods?: M
105
+
99
106
  [index: string]: any
100
107
  }
101
108
 
@@ -108,14 +115,16 @@ interface Context {
108
115
  triggerEvent: WechatMiniprogram.Component.InstanceMethods<Record<string, any>>['triggerEvent']
109
116
  refs: ObjectOf<WechatMiniprogram.NodesRef & ComponentIns<{}, {}, {}, {}, []>>
110
117
  asyncRefs: ObjectOf<Promise<WechatMiniprogram.NodesRef & ComponentIns<{}, {}, {}, {}, []>>>
118
+
111
119
  forceUpdate (params?: object, callback?: () => void): void
120
+
112
121
  selectComponent: ReplaceWxComponentIns['selectComponent']
113
122
  selectAllComponents: ReplaceWxComponentIns['selectAllComponents']
114
123
  createSelectorQuery: WechatMiniprogram.Component.InstanceMethods<Record<string, any>>['createSelectorQuery']
115
124
  createIntersectionObserver: WechatMiniprogram.Component.InstanceMethods<Record<string, any>>['createIntersectionObserver']
116
125
  }
117
126
 
118
- interface ComponentOpt<D, P, C, M, Mi extends Array<any>, S extends Record<any, any>> extends Partial<WechatMiniprogram.Component.Lifetimes & WechatMiniprogram.Component.OtherOption>{
127
+ interface ComponentOpt<D extends Data, P extends Properties, C, M extends Methods, Mi extends Array<any>, S extends Record<any, any>> extends Partial<WechatMiniprogram.Component.Lifetimes & WechatMiniprogram.Component.OtherOption> {
119
128
  data?: D
120
129
  properties?: P
121
130
  computed?: C
@@ -133,15 +142,15 @@ interface ComponentOpt<D, P, C, M, Mi extends Array<any>, S extends Record<any,
133
142
  [index: string]: any
134
143
  }
135
144
 
136
- type PageOpt<D, P, C, M, Mi extends Array<any>, S extends Record<any, any>> =
145
+ type PageOpt<D extends Data, P extends Properties, C, M extends Methods, Mi extends Array<any>, S extends Record<any, any>> =
137
146
  ComponentOpt<D, P, C, M, Mi, S>
138
147
  & Partial<WechatMiniprogram.Page.ILifetime>
139
148
 
140
- type ThisTypedPageOpt<D extends AnyObject, P, C, M, Mi extends Array<any>, S extends Record<any, any>, O = {}> =
149
+ type ThisTypedPageOpt<D extends Data, P extends Properties, C, M extends Methods, Mi extends Array<any>, S extends Record<any, any>, O = {}> =
141
150
  PageOpt<D, P, C, M, Mi, S>
142
151
  & ThisType<ComponentIns<D, P, C, M, Mi, S, O>> & O
143
152
 
144
- type ThisTypedComponentOpt<D extends AnyObject, P, C, M, Mi extends Array<any>, S extends Record<any, any>, O = {}> =
153
+ type ThisTypedComponentOpt<D extends Data, P extends Properties, C, M extends Methods, Mi extends Array<any>, S extends Record<any, any>, O = {}> =
145
154
  ComponentOpt<D, P, C, M, Mi, S>
146
155
  & ThisType<ComponentIns<D, P, C, M, Mi, S, O>> & O
147
156
 
@@ -169,13 +178,17 @@ type MpxComProps<O> = { $rawOptions: O }
169
178
 
170
179
  export interface MpxComponentIns {
171
180
  $refs: ObjectOf<WechatMiniprogram.NodesRef & ComponentIns<{}, {}, {}, {}, []>>
172
- $asyncRefs : ObjectOf<Promise<WechatMiniprogram.NodesRef & ComponentIns<{}, {}, {}, {}, []>>>
181
+ $asyncRefs: ObjectOf<Promise<WechatMiniprogram.NodesRef & ComponentIns<{}, {}, {}, {}, []>>>
173
182
  $set: typeof set
174
183
  $remove: typeof del
175
184
  $delete: typeof del
185
+
176
186
  $watch (expr: string | (() => any), handler: WatchHandler | WatchOptWithHandler, options?: WatchOpt): () => void
187
+
177
188
  $forceUpdate (params?: object, callback?: () => void): void
189
+
178
190
  $nextTick (fn: () => void): void
191
+
179
192
  $i18n: {
180
193
  locale: string
181
194
  fallbackLocale: string
@@ -184,6 +197,7 @@ export interface MpxComponentIns {
184
197
  $tc: typeof tc
185
198
  $te: typeof te
186
199
  $tm: typeof tm
200
+
187
201
  [k: string]: any
188
202
  }
189
203
 
@@ -193,17 +207,16 @@ interface ReplaceWxComponentIns {
193
207
  selectAllComponents (selector: string): Array<ComponentIns<{}, {}, {}, {}, []>>
194
208
  }
195
209
 
196
- type WxComponentIns<D extends AnyObject> =
197
- ReplaceWxComponentIns
198
- & WechatMiniprogram.Component.InstanceProperties
199
- & WechatMiniprogram.Component.InstanceMethods<D>
210
+ type WxComponentIns<D extends Data = {}, P extends Properties = {}, M extends Methods = {}> =
211
+ Omit<WechatMiniprogram.Component.Instance<D, P, M>, 'selectComponent' | 'selectAllComponents'>
212
+ & ReplaceWxComponentIns
200
213
 
201
- type ComponentIns<D extends AnyObject, P, C, M, Mi extends Array<any>, S extends Record<any, any> = {}, O = {}> =
214
+ type ComponentIns<D extends Data = {}, P extends Properties = {}, C = {}, M extends Methods = {}, Mi extends Array<any> = [], S extends Record<any, any> = {}, O = {}> =
202
215
  GetDataType<D> & UnboxMixinsField<Mi, 'data'> &
203
216
  M & UnboxMixinsField<Mi, 'methods'> & { [K in keyof S]: S[K] extends Ref<infer V> ? V : S[K] } &
204
217
  GetPropsType<P & UnboxMixinsField<Mi, 'properties'>> &
205
218
  GetComputedType<C & UnboxMixinsField<Mi, 'computed'>> &
206
- WxComponentIns<D> & MpxComponentIns & MpxComProps<O>
219
+ WxComponentIns<D, P, M> & MpxComponentIns & MpxComProps<O>
207
220
 
208
221
  interface CreateConfig {
209
222
  customCtor: any
@@ -225,7 +238,10 @@ export function createApp<T extends WechatMiniprogram.IAnyObject> (opt: WechatMi
225
238
 
226
239
  type MixinType = 'app' | 'page' | 'component'
227
240
 
228
- export function injectMixins (mixins: object | Array<object>, options?: MixinType | MixinType[] | { types?: MixinType | MixinType[], stage?: number }): Mpx
241
+ export function injectMixins (mixins: object | Array<object>, options?: MixinType | MixinType[] | {
242
+ types?: MixinType | MixinType[],
243
+ stage?: number
244
+ }): Mpx
229
245
 
230
246
  // export function watch (expr: string | (() => any), handler: WatchHandler | WatchOptWithHandler, options?: WatchOpt): () => void
231
247
 
@@ -235,6 +251,11 @@ interface AnyConstructor {
235
251
  prototype: any
236
252
  }
237
253
 
254
+ interface WebviewConfig {
255
+ hostWhitelists?: Array<string>
256
+ apiImplementations?: object
257
+ }
258
+
238
259
  interface MpxConfig {
239
260
  useStrictDiff: boolean
240
261
  ignoreWarning: boolean | string | RegExp | ((msg: string, location: string, e: Error) => boolean)
@@ -244,7 +265,8 @@ interface MpxConfig {
244
265
  proxyEventHandler: (e: Event) => any | null
245
266
  setDataHandler: (data: object, target: ComponentIns<{}, {}, {}, {}, []>) => any | null
246
267
  forceFlushSync: boolean,
247
- webRouteConfig: object
268
+ webRouteConfig: object,
269
+ webviewConfig?: WebviewConfig
248
270
  }
249
271
 
250
272
  type SupportedMode = 'wx' | 'ali' | 'qq' | 'swan' | 'tt' | 'web' | 'qa'
@@ -257,11 +279,11 @@ interface ImplementOptions {
257
279
 
258
280
  export function toPureObject<T extends object> (obj: T): T
259
281
 
260
- declare type PluginInstallFunction = (app: Mpx, ...options: any[]) => any;
282
+ declare type PluginInstallFunction = (app: Mpx, ...options: any[]) => any
261
283
 
262
284
  export type Plugin = PluginInstallFunction | {
263
- install: PluginInstallFunction;
264
- };
285
+ install: PluginInstallFunction
286
+ }
265
287
 
266
288
  export interface Mpx {
267
289
  getMixin: typeof getMixin
@@ -318,7 +340,7 @@ export interface Ref<T = any> {
318
340
  * We need this to be in public d.ts but don't want it to show up in IDE
319
341
  * autocomplete, so we use a private Symbol instead.
320
342
  */
321
- [RefSymbol]: true
343
+ [RefSymbol]: true
322
344
  }
323
345
 
324
346
  type CollectionTypes = IterableCollections | WeakCollections
@@ -427,7 +449,11 @@ export interface WatchOptions extends WatchEffectOptions {
427
449
 
428
450
  interface EffectScope {
429
451
  run<T> (fn: () => T): T | undefined // 如果作用域不活跃就为 undefined
430
- stop (): void
452
+ stop (fromParent?: boolean): void
453
+
454
+ pause (): void
455
+
456
+ resume (ignoreDirty?: boolean): void
431
457
  }
432
458
 
433
459
 
@@ -486,7 +512,7 @@ export function reactive<T extends object> (target: T): Reactive<T>
486
512
 
487
513
  export function isReactive (value: unknown): boolean
488
514
 
489
- export function markRaw<T extends object>(value: T): T
515
+ export function markRaw<T extends object> (value: T): T
490
516
 
491
517
  export function shallowReactive<T extends object> (target: T): ShallowReactive<T>
492
518
 
@@ -566,6 +592,7 @@ export function onBeforeUnmount (callback: () => void): void
566
592
  export function onUnmounted (callback: () => void): void
567
593
 
568
594
  export function onLoad<T extends Record<string, string | undefined>> (callback: (query: T) => void): void
595
+
569
596
  // wechat dose not have generics
570
597
  // export function onLoad (callback: WechatMiniprogram.Page.ILifetime['onLoad']): void
571
598
 
@@ -592,7 +619,7 @@ export function onTabItemTap (callback: WechatMiniprogram.Page.ILifetime['onTabI
592
619
  export function onSaveExitState (callback: () => void): void
593
620
 
594
621
  // get instance
595
- export function getCurrentInstance<T extends MpxComponentIns & WechatMiniprogram.Component.Instance<{}, {}, {}>> (): T
622
+ export function getCurrentInstance<T extends ComponentIns<{}, {}, {}>> (): { proxy: T, [x: string]: any }
596
623
 
597
624
  // I18n
598
625
  export function useI18n<Options extends {
@@ -612,8 +639,7 @@ type InferDefaults<T> = {
612
639
  [K in keyof T]?: InferDefault<T, NotUndefined<T[K]>>
613
640
  }
614
641
 
615
- type InferDefault<P, T> = T extends
616
- | null
642
+ type InferDefault<P, T> = T extends | null
617
643
  | number
618
644
  | string
619
645
  | boolean
@@ -642,7 +668,7 @@ export const ONHIDE: string
642
668
  export const ONRESIZE: string
643
669
 
644
670
  declare global {
645
- const defineProps: (<T>(props: T) => Readonly<GetPropsType<T>>) & (<T>() => Readonly<T>)
671
+ const defineProps: (<T extends Properties = {}>(props: T) => Readonly<GetPropsType<T>>) & (<T>() => Readonly<T>)
646
672
  const defineOptions: <D extends Data = {}, P extends Properties = {}, C = {}, M extends Methods = {}, Mi extends Array<any> = [], S extends AnyObject = {}, O extends AnyObject = {}> (opt: ThisTypedComponentOpt<D, P, C, M, Mi, S, O>) => void
647
673
  const defineExpose: <E extends AnyObject = AnyObject>(exposed?: E) => void
648
674
  const useContext: () => Context
package/@types/node.d.ts CHANGED
@@ -12,19 +12,21 @@ declare let process: {
12
12
  env: EnvType
13
13
  }
14
14
 
15
- declare namespace __WebpackModuleApi {
16
-
15
+ declare namespace __WebpackModuleApi {
17
16
  interface RequireContext {
18
- keys(): string[];
17
+ keys (): string[];
18
+
19
19
  (id: string): any;
20
- <T>(id: string): T;
21
- resolve(id: string): string;
20
+
21
+ <T> (id: string): T;
22
+
23
+ resolve (id: string): string;
24
+
22
25
  /** The module id of the context module. This may be useful for module.hot.accept. */
23
26
  id: string;
24
27
  }
25
28
  }
26
29
 
27
- declare namespace require {
28
- export function context(path: string, deep?: boolean, filter?: RegExp, mode?: 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once'): __WebpackModuleApi.RequireContext;
29
- export function async<T>(path: string): Promise<T>
30
+ interface Require {
31
+ context (path: string, deep?: boolean, filter?: RegExp, mode?: 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once'): __WebpackModuleApi.RequireContext
30
32
  }
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@mpxjs/core",
3
- "version": "2.8.39",
3
+ "version": "2.8.40-test.2",
4
4
  "description": "mpx runtime core",
5
5
  "keywords": [
6
6
  "miniprogram",
7
7
  "mpx"
8
8
  ],
9
9
  "author": "donghongping",
10
- "license": "Apache",
10
+ "license": "Apache-2.0",
11
11
  "module": "src/index.js",
12
12
  "types": "@types/index.d.ts",
13
13
  "directories": {
@@ -19,15 +19,15 @@
19
19
  ],
20
20
  "main": "src/index.js",
21
21
  "dependencies": {
22
- "@mpxjs/utils": "^2.8.15",
22
+ "@mpxjs/utils": "^2.8.40-test.2",
23
23
  "lodash": "^4.1.1",
24
- "miniprogram-api-typings": "^3.0.2"
24
+ "miniprogram-api-typings": "^3.10.0"
25
25
  },
26
26
  "peerDependencies": {
27
- "@mpxjs/api-proxy": "^2.7.44",
28
- "@mpxjs/store": "^2.8.0",
27
+ "@mpxjs/api-proxy": "^2.9.0",
28
+ "@mpxjs/store": "^2.9.0",
29
29
  "vue": "^2.7.10",
30
- "vue-demi": "^0.13.11",
30
+ "vue-demi": "^0.14.6",
31
31
  "vue-i18n": "^8.27.2",
32
32
  "vue-i18n-bridge": "^9.2.2"
33
33
  },
@@ -47,5 +47,5 @@
47
47
  "url": "https://github.com/didi/mpx/issues"
48
48
  },
49
49
  "sideEffects": false,
50
- "gitHead": "c11c93eeb5315c5ff54df7ace05709a21bdaea53"
50
+ "gitHead": "7b1911025a2eb47eddc046775f17b6f1405fdd54"
51
51
  }
@@ -19,7 +19,7 @@ export function injectMixins (mixins, options = {}) {
19
19
  }
20
20
  }
21
21
 
22
- let types = options.types || ['app', 'page', 'component']
22
+ let types = options.types || ['page', 'component']
23
23
  const stage = options.stage || -1
24
24
 
25
25
  if (typeof types === 'string') {
@@ -10,6 +10,7 @@ export const ONLOAD = '__onLoad__'
10
10
  export const ONSHOW = '__onShow__'
11
11
  export const ONHIDE = '__onHide__'
12
12
  export const ONRESIZE = '__onResize__'
13
+ export const SERVERPREFETCH = '__serverPrefetch__'
13
14
 
14
15
  export const INNER_LIFECYCLES = [
15
16
  BEFORECREATE,
@@ -19,6 +20,7 @@ export const INNER_LIFECYCLES = [
19
20
  BEFOREUPDATE,
20
21
  UPDATED,
21
22
  BEFOREUNMOUNT,
23
+ SERVERPREFETCH,
22
24
  UNMOUNTED,
23
25
  ONLOAD,
24
26
  ONSHOW,
@@ -314,17 +314,19 @@ export function mergeToArray (parent, child, key) {
314
314
  function composeHooks (target, includes) {
315
315
  Object.keys(target).forEach(key => {
316
316
  if (!includes || includes[key]) {
317
- const hooksArr = target[key]
318
- hooksArr && (target[key] = function (...args) {
319
- let result
320
- for (let i = 0; i < hooksArr.length; i++) {
321
- if (typeof hooksArr[i] === 'function') {
322
- const data = hooksArr[i].apply(this, args)
323
- data !== undefined && (result = data)
317
+ const hooks = target[key]
318
+ if (Array.isArray(hooks)) {
319
+ target[key] = function (...args) {
320
+ let result
321
+ for (let i = 0; i < hooks.length; i++) {
322
+ if (typeof hooks[i] === 'function') {
323
+ const data = hooks[i].apply(this, args)
324
+ data !== undefined && (result = data)
325
+ }
324
326
  }
327
+ return result
325
328
  }
326
- return result
327
- })
329
+ }
328
330
  }
329
331
  })
330
332
  }
@@ -352,7 +354,7 @@ function transformHOOKS (options) {
352
354
  const componentHooksMap = makeMap(convertRule.lifecycle.component)
353
355
  for (const key in options) {
354
356
  // 使用Component创建page实例,页面专属生命周期&自定义方法需写在methods内部
355
- if (typeof options[key] === 'function' && key !== 'dataFn' && key !== 'setup' && !componentHooksMap[key]) {
357
+ if (typeof options[key] === 'function' && key !== 'dataFn' && key !== 'setup' && key !== 'serverPrefetch' && !componentHooksMap[key]) {
356
358
  if (!options.methods) options.methods = {}
357
359
  options.methods[key] = options[key]
358
360
  delete options[key]
package/src/core/proxy.js CHANGED
@@ -26,7 +26,8 @@ import {
26
26
  getFirstKey,
27
27
  callWithErrorHandling,
28
28
  warn,
29
- error
29
+ error,
30
+ getEnvObj
30
31
  } from '@mpxjs/utils'
31
32
  import {
32
33
  BEFORECREATE,
@@ -36,6 +37,7 @@ import {
36
37
  BEFOREUPDATE,
37
38
  UPDATED,
38
39
  BEFOREUNMOUNT,
40
+ SERVERPREFETCH,
39
41
  UNMOUNTED,
40
42
  ONLOAD,
41
43
  ONSHOW,
@@ -45,6 +47,8 @@ import {
45
47
 
46
48
  let uid = 0
47
49
 
50
+ const envObj = getEnvObj()
51
+
48
52
  class RenderTask {
49
53
  resolved = false
50
54
 
@@ -235,14 +239,14 @@ export default class MpxProxy {
235
239
  const setupResult = callWithErrorHandling(setup, this, 'setup function', [
236
240
  this.props,
237
241
  {
238
- triggerEvent: this.target.triggerEvent.bind(this.target),
242
+ triggerEvent: this.target.triggerEvent ? this.target.triggerEvent.bind(this.target) : noop,
239
243
  refs: this.target.$refs,
240
244
  asyncRefs: this.target.$asyncRefs,
241
245
  forceUpdate: this.forceUpdate.bind(this),
242
246
  selectComponent: this.target.selectComponent.bind(this.target),
243
247
  selectAllComponents: this.target.selectAllComponents.bind(this.target),
244
- createSelectorQuery: this.target.createSelectorQuery.bind(this.target),
245
- createIntersectionObserver: this.target.createIntersectionObserver.bind(this.target)
248
+ createSelectorQuery: this.target.createSelectorQuery ? this.target.createSelectorQuery.bind(this.target) : envObj.createSelectorQuery.bind(envObj),
249
+ createIntersectionObserver: this.target.createIntersectionObserver ? this.target.createIntersectionObserver.bind(this.target) : envObj.createIntersectionObserver.bind(envObj)
246
250
  }
247
251
  ])
248
252
  if (!isObject(setupResult)) {
@@ -308,7 +312,16 @@ export default class MpxProxy {
308
312
  watch (source, cb, options) {
309
313
  const target = this.target
310
314
  const getter = isString(source)
311
- ? () => getByPath(target, source)
315
+ ? () => {
316
+ // for watch multi path string like 'a.b,c,d'
317
+ if (source.indexOf(',') > -1) {
318
+ return source.split(',').map(path => {
319
+ return getByPath(target, path.trim())
320
+ })
321
+ } else {
322
+ return getByPath(target, source)
323
+ }
324
+ }
312
325
  : source.bind(target)
313
326
 
314
327
  if (isObject(cb)) {
@@ -526,6 +539,10 @@ export default class MpxProxy {
526
539
  initRender () {
527
540
  if (this.options.__nativeRender__) return this.doRender()
528
541
 
542
+ const _i = this.target._i.bind(this.target)
543
+ const _c = this.target._c.bind(this.target)
544
+ const _r = this.target._r.bind(this.target)
545
+ const _sc = this.target._sc.bind(this.target)
529
546
  const effect = this.effect = new ReactiveEffect(() => {
530
547
  // pre render for props update
531
548
  if (this.propsUpdatedFlag) {
@@ -534,7 +551,7 @@ export default class MpxProxy {
534
551
 
535
552
  if (this.target.__injectedRender) {
536
553
  try {
537
- return this.target.__injectedRender()
554
+ return this.target.__injectedRender(_i, _c, _r, _sc)
538
555
  } catch (e) {
539
556
  warn('Failed to execute render function, degrade to full-set-data mode.', this.options.mpxFileResource, e)
540
557
  this.render()
@@ -604,7 +621,9 @@ export default class MpxProxy {
604
621
 
605
622
  export let currentInstance = null
606
623
 
607
- export const getCurrentInstance = () => currentInstance?.target
624
+ export const getCurrentInstance = () => {
625
+ return currentInstance && { proxy: currentInstance?.target }
626
+ }
608
627
 
609
628
  export const setCurrentInstance = (instance) => {
610
629
  currentInstance = instance
@@ -641,6 +660,7 @@ export const onLoad = createHook(ONLOAD)
641
660
  export const onShow = createHook(ONSHOW)
642
661
  export const onHide = createHook(ONHIDE)
643
662
  export const onResize = createHook(ONRESIZE)
663
+ export const onServerPrefetch = createHook(SERVERPREFETCH)
644
664
  export const onPullDownRefresh = createHook('__onPullDownRefresh__')
645
665
  export const onReachBottom = createHook('__onReachBottom__')
646
666
  export const onShareAppMessage = createHook('__onShareAppMessage__')
package/src/index.js CHANGED
@@ -29,6 +29,7 @@ export {
29
29
  UPDATED,
30
30
  BEFOREUNMOUNT,
31
31
  UNMOUNTED,
32
+ SERVERPREFETCH,
32
33
  ONLOAD,
33
34
  ONSHOW,
34
35
  ONHIDE,
@@ -42,6 +43,7 @@ export {
42
43
  onUpdated,
43
44
  onBeforeUnmount,
44
45
  onUnmounted,
46
+ onServerPrefetch,
45
47
  onLoad,
46
48
  onShow,
47
49
  onHide,
@@ -135,7 +137,13 @@ Mpx.config = {
135
137
  proxyEventHandler: null,
136
138
  setDataHandler: null,
137
139
  forceFlushSync: false,
138
- webRouteConfig: {}
140
+ webRouteConfig: {},
141
+ /*
142
+ 支持两个属性
143
+ hostWhitelists Array 类型 支持h5域名白名单安全校验
144
+ apiImplementations webview JSSDK接口 例如getlocation
145
+ */
146
+ webviewConfig: {}
139
147
  }
140
148
 
141
149
  global.__mpx = Mpx
@@ -119,7 +119,9 @@ export class ReactiveEffect {
119
119
  }
120
120
 
121
121
  pause () {
122
- this.pausedState = PausedState.paused
122
+ if (this.pausedState !== PausedState.dirty) {
123
+ this.pausedState = PausedState.paused
124
+ }
123
125
  }
124
126
 
125
127
  resume (ignoreDirty = false) {
@@ -4,6 +4,19 @@ export default function pageRouteMixin (mixinType) {
4
4
  return {
5
5
  beforeCreate () {
6
6
  this.route = this.$options.__mpxPageRoute || ''
7
+ },
8
+ methods: {
9
+ getOpenerEventChannel () {
10
+ const router = global.__mpxRouter
11
+ const eventChannel = router && router.eventChannelMap[this.route]
12
+ return eventChannel || {}
13
+ }
14
+ }
15
+ }
16
+ }
17
+ return {
18
+ methods: {
19
+ getOpenerEventChannel () {
7
20
  }
8
21
  }
9
22
  }
@@ -41,6 +41,7 @@ export default function pageScrollMixin (mixinType) {
41
41
  return {
42
42
  mounted () {
43
43
  this.__lastScrollY = 0
44
+ this.__originalOverflow = document.body.style.overflow
44
45
  },
45
46
  activated () {
46
47
  if (!refreshMs()) {
@@ -72,19 +73,22 @@ export default function pageScrollMixin (mixinType) {
72
73
  }
73
74
  },
74
75
  deactivated () {
75
- if (ms) {
76
+ if (ms) { // 保存滚动位置, 用于 keep-alive
76
77
  this.__lastScrollY = getScrollTop()
77
- ms.destroy()
78
- hideLoading(this)
79
78
  }
79
+ this.__uninstallMpxScroll()
80
80
  },
81
81
  beforeDestroy () {
82
- if (ms) {
83
- ms.destroy()
84
- hideLoading(this)
85
- }
82
+ this.__uninstallMpxScroll()
86
83
  },
87
84
  methods: {
85
+ __uninstallMpxScroll () {
86
+ if (ms) {
87
+ ms.destroy()
88
+ hideLoading(this)
89
+ document.body.style.overflow = this.__originalOverflow // 恢复原有 overflow, 避免影响其他页面
90
+ }
91
+ },
88
92
  __mpxPullDownHandler (autoStop = false, isRefresh = false) {
89
93
  this.__pullingDown = true
90
94
  // 同微信保持一致
@@ -1,4 +1,5 @@
1
1
  import {
2
+ BEFORECREATE,
2
3
  CREATED,
3
4
  ONHIDE,
4
5
  ONSHOW,
@@ -47,6 +48,18 @@ if (isBrowser) {
47
48
  window.addEventListener('resize', onResize)
48
49
  }
49
50
 
51
+ function getParentPage (vm) {
52
+ let parent = vm.$parent
53
+ while (parent) {
54
+ if (parent.route) {
55
+ return parent
56
+ } else if (parent.$page) {
57
+ return parent.$page
58
+ }
59
+ parent = parent.$parent
60
+ }
61
+ }
62
+
50
63
  export default function pageStatusMixin (mixinType) {
51
64
  const mixin = {}
52
65
 
@@ -63,33 +76,44 @@ export default function pageStatusMixin (mixinType) {
63
76
  },
64
77
  created () {
65
78
  // onLoad应该在用户声明周期CREATED后再执行,故此处使用原生created声明周期来触发onLoad
66
- const query = (global.__mpxRouter && global.__mpxRouter.currentRoute && global.__mpxRouter.currentRoute.query) || {}
79
+ const query = this.$root.$options?.router?.currentRoute?.query || {}
67
80
  this.__mpxProxy.callHook(ONLOAD, [query])
68
81
  }
69
82
  })
70
83
  }
71
84
 
85
+ // 创建组件时记录当前所属page,用于驱动pageLifetimes和onShow/onHide钩子
86
+ if (mixinType === 'component') {
87
+ Object.assign(mixin, {
88
+ [BEFORECREATE] () {
89
+ this.$page = getParentPage(this)
90
+ }
91
+ })
92
+ }
93
+
72
94
  Object.assign(mixin, {
73
95
  [CREATED] () {
74
- const pageInstance = mixinType === 'page' ? this : getCurrentPageInstance()
75
- if (pageInstance) {
76
- this.$watch(() => pageInstance.mpxPageStatus, status => {
77
- if (!status) return
78
- if (status === 'show') this.__mpxProxy.callHook(ONSHOW)
79
- if (status === 'hide') this.__mpxProxy.callHook(ONHIDE)
80
- const pageLifetimes = this.__mpxProxy.options.pageLifetimes
81
- if (pageLifetimes) {
82
- if (/^resize/.test(status) && isFunction(pageLifetimes.resize)) {
83
- // resize
84
- pageLifetimes.resize.call(this, systemInfo)
85
- } else if (isFunction(pageLifetimes[status])) {
86
- // show & hide
87
- pageLifetimes[status].call(this)
96
+ if (isBrowser) {
97
+ const pageInstance = mixinType === 'page' ? this : this.$page
98
+ if (pageInstance) {
99
+ this.$watch(() => pageInstance.mpxPageStatus, status => {
100
+ if (!status) return
101
+ if (status === 'show') this.__mpxProxy.callHook(ONSHOW)
102
+ if (status === 'hide') this.__mpxProxy.callHook(ONHIDE)
103
+ const pageLifetimes = this.__mpxProxy.options.pageLifetimes
104
+ if (pageLifetimes) {
105
+ if (/^resize/.test(status) && isFunction(pageLifetimes.resize)) {
106
+ // resize
107
+ pageLifetimes.resize.call(this, systemInfo)
108
+ } else if (isFunction(pageLifetimes[status])) {
109
+ // show & hide
110
+ pageLifetimes[status].call(this)
111
+ }
88
112
  }
89
- }
90
- }, {
91
- sync: true
92
- })
113
+ }, {
114
+ sync: true
115
+ })
116
+ }
93
117
  }
94
118
  }
95
119
  })
@@ -1,4 +1,4 @@
1
- import { setByPath, error, hasOwn } from '@mpxjs/utils'
1
+ import { setByPath, error, hasOwn, dash2hump } from '@mpxjs/utils'
2
2
  import Mpx from '../../index'
3
3
 
4
4
  const datasetReg = /^data-(.+)$/
@@ -35,7 +35,9 @@ export default function proxyEventMixin () {
35
35
  let fallbackType = ''
36
36
  if (type === 'begin' || type === 'end') {
37
37
  // 地图的 regionchange 事件会派发 e.type 为 begin 和 end 的事件
38
- fallbackType = 'regionchange'
38
+ fallbackType = __mpx_mode__ === 'ali' ? 'regionChange' : 'regionchange'
39
+ } else if (/-([a-z])/.test(type)) {
40
+ fallbackType = dash2hump(type)
39
41
  } else if (__mpx_mode__ === 'ali') {
40
42
  fallbackType = type.replace(/^./, i => i.toLowerCase())
41
43
  }
@@ -99,15 +101,8 @@ export default function proxyEventMixin () {
99
101
  const eventObj = {
100
102
  type: eventName,
101
103
  timeStamp,
102
- target: {
103
- id,
104
- dataset,
105
- targetDataset: dataset
106
- },
107
- currentTarget: {
108
- id,
109
- dataset
110
- },
104
+ target: { id, dataset, targetDataset: dataset },
105
+ currentTarget: { id, dataset },
111
106
  detail: eventDetail
112
107
  }
113
108
  handler.call(this, eventObj)
@@ -18,11 +18,6 @@ export default function proxyEventMixin () {
18
18
  const originValue = valuePath.reduce((acc, cur) => acc[cur], $event.detail)
19
19
  const value = filterMethod ? (innerFilter[filterMethod] ? innerFilter[filterMethod](originValue) : typeof this[filterMethod] === 'function' && this[filterMethod]) : originValue
20
20
  setByPath(this, expr, value)
21
- },
22
- getOpenerEventChannel () {
23
- const router = global.__mpxRouter
24
- const eventChannel = router && router.__mpxAction && router.__mpxAction.eventChannel
25
- return eventChannel
26
21
  }
27
22
  }
28
23
  }
@@ -1,5 +1,5 @@
1
1
  import { BEFOREMOUNT, UPDATED } from '../../core/innerLifecycle'
2
- import * as webApi from '@mpxjs/api-proxy/src/web/api'
2
+ import { createSelectorQuery } from '@mpxjs/api-proxy'
3
3
 
4
4
  function getEl (ref) {
5
5
  if (ref && ref.nodeType === 1) return ref
@@ -8,19 +8,19 @@ function getEl (ref) {
8
8
 
9
9
  function processRefs (refs) {
10
10
  Object.keys(refs).forEach((key) => {
11
- const matched = /^__mpx_ref_([^_]+)__$/.exec(key)
11
+ const matched = /^__mpx_ref_(.+)__$/.exec(key)
12
12
  const rKey = matched && matched[1]
13
13
  if (rKey) {
14
14
  const ref = refs[key]
15
15
  if (Array.isArray(ref)) {
16
16
  if (getEl(ref[0])) {
17
- refs[rKey] = webApi.createSelectorQuery().in(this).selectAll(ref.map(getEl))
17
+ refs[rKey] = createSelectorQuery().in(this).selectAll(ref.map(getEl))
18
18
  } else {
19
19
  refs[rKey] = ref
20
20
  }
21
21
  } else {
22
22
  if (getEl(ref)) {
23
- refs[rKey] = webApi.createSelectorQuery().in(this).select(getEl(ref))
23
+ refs[rKey] = createSelectorQuery().in(this).select(getEl(ref))
24
24
  } else {
25
25
  refs[rKey] = ref
26
26
  }
@@ -1,4 +1,4 @@
1
- import { isObject } from '@mpxjs/utils'
1
+ import { getByPath, hasOwn, isObject } from '@mpxjs/utils'
2
2
 
3
3
  export default function renderHelperMixin () {
4
4
  return {
@@ -21,10 +21,21 @@ export default function renderHelperMixin () {
21
21
  }
22
22
  }
23
23
  },
24
+ // collect
24
25
  _c (key, value) {
26
+ if (hasOwn(this.__mpxProxy.renderData, key)) {
27
+ return this.__mpxProxy.renderData[key]
28
+ }
29
+ if (value === undefined) {
30
+ value = getByPath(this, key)
31
+ }
25
32
  this.__mpxProxy.renderData[key] = value
26
33
  return value
27
34
  },
35
+ // simple collect
36
+ _sc (key) {
37
+ return (this.__mpxProxy.renderData[key] = this[key])
38
+ },
28
39
  _r () {
29
40
  this.__mpxProxy.renderWithData()
30
41
  }
@@ -1,11 +1,12 @@
1
1
  import transferOptions from '../core/transferOptions'
2
2
  import mergeOptions from '../core/mergeOptions'
3
3
  import builtInKeysMap from './patch/builtInKeysMap'
4
- import { makeMap, spreadProp } from '@mpxjs/utils'
4
+ import { makeMap, spreadProp, isBrowser } from '@mpxjs/utils'
5
+ import { mergeLifecycle } from '../convertor/mergeLifecycle'
5
6
  import * as webLifecycle from '../platform/patch/web/lifecycle'
6
7
  import Mpx from '../index'
7
8
 
8
- const webAppHooksMap = makeMap(webLifecycle.LIFECYCLE.APP_HOOKS)
9
+ const webAppHooksMap = makeMap(mergeLifecycle(webLifecycle.LIFECYCLE).app)
9
10
 
10
11
  function filterOptions (options, appData) {
11
12
  const newOptions = {}
@@ -35,7 +36,7 @@ export default function createApp (option, config = {}) {
35
36
  created () {
36
37
  Object.assign(this, Mpx.prototype)
37
38
  Object.assign(this, appData)
38
- const current = (global.__mpxRouter && global.__mpxRouter.currentRoute) || {}
39
+ const current = this.$root.$options?.router?.currentRoute || {}
39
40
  const options = {
40
41
  path: current.path && current.path.replace(/^\//, ''),
41
42
  query: current.query,
@@ -49,19 +50,24 @@ export default function createApp (option, config = {}) {
49
50
  hide: [],
50
51
  error: []
51
52
  }
52
- if (this.$options.onShow) {
53
- this.$options.onShow.call(this, options)
54
- global.__mpxAppCbs.show.push(this.$options.onShow.bind(this))
55
- }
56
- if (this.$options.onHide) {
57
- global.__mpxAppCbs.hide.push(this.$options.onHide.bind(this))
58
- }
59
- if (this.$options.onError) {
60
- global.__mpxAppCbs.error.push(this.$options.onError.bind(this))
53
+ if (isBrowser) {
54
+ if (this.$options.onShow) {
55
+ this.$options.onShow.call(this, options)
56
+ global.__mpxAppCbs.show.push(this.$options.onShow.bind(this))
57
+ }
58
+ if (this.$options.onHide) {
59
+ global.__mpxAppCbs.hide.push(this.$options.onHide.bind(this))
60
+ }
61
+ if (this.$options.onError) {
62
+ global.__mpxAppCbs.error.push(this.$options.onError.bind(this))
63
+ }
61
64
  }
62
65
  }
63
66
  })
64
67
  } else {
68
+ if (option.onAppInit) {
69
+ option.onAppInit()
70
+ }
65
71
  builtInMixins.push({
66
72
  onLaunch () {
67
73
  Object.assign(this, Mpx.prototype)
@@ -77,6 +83,9 @@ export default function createApp (option, config = {}) {
77
83
  global.__mpxOptionsMap = global.__mpxOptionsMap || {}
78
84
  global.__mpxOptionsMap[global.currentModuleId] = defaultOptions
79
85
  global.getApp = function () {
86
+ if (!isBrowser) {
87
+ console.error('[Mpx runtime error]: Dangerous API! global.getApp method is running in non browser environments')
88
+ }
80
89
  return appData
81
90
  }
82
91
  } else {
@@ -1,8 +1,60 @@
1
- import {
2
- effectScope as vueEffectScope,
3
- getCurrentScope as getCurrentVueScope,
4
- onScopeDispose
5
- } from 'vue'
1
+ import { EffectScope } from 'vue'
2
+ import { hasOwn } from '@mpxjs/utils'
3
+ import { PausedState } from '../../helper/const'
4
+
5
+ const hackEffectScope = () => {
6
+ EffectScope.prototype.pause = function () {
7
+ if (this.active) {
8
+ let i, l
9
+ for (i = 0, l = this.effects.length; i < l; i++) {
10
+ const effect = this.effects[i]
11
+ // vue2.7中存在对于watcher实例方法的重写(doWatch),因此无法通过修改Watcher.prototype统一实现pause和resume,只能逐个实例修改实现
12
+ if (!hasOwn(effect, 'pausedState')) {
13
+ effect.pausedState = PausedState.resumed
14
+ const rawUpdate = effect.update
15
+ effect.update = function () {
16
+ if (effect.pausedState !== PausedState.resumed) {
17
+ effect.pausedState = PausedState.dirty
18
+ } else {
19
+ rawUpdate.call(effect)
20
+ }
21
+ }
22
+ }
23
+ if (effect.pausedState !== PausedState.dirty) {
24
+ effect.pausedState = PausedState.paused
25
+ }
26
+ }
27
+ if (this.scopes) {
28
+ for (i = 0, l = this.scopes.length; i < l; i++) {
29
+ this.scopes[i].pause()
30
+ }
31
+ }
32
+ }
33
+ }
34
+
35
+ EffectScope.prototype.resume = function (ignoreDirty = false) {
36
+ if (this.active) {
37
+ let i, l
38
+ for (i = 0, l = this.effects.length; i < l; i++) {
39
+ const effect = this.effects[i]
40
+ if (hasOwn(effect, 'pausedState')) {
41
+ const lastPausedState = effect.pausedState
42
+ effect.pausedState = PausedState.resumed
43
+ if (!ignoreDirty && lastPausedState === PausedState.dirty) {
44
+ effect.update()
45
+ }
46
+ }
47
+ }
48
+ if (this.scopes) {
49
+ for (i = 0, l = this.scopes.length; i < l; i++) {
50
+ this.scopes[i].resume(ignoreDirty)
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+ hackEffectScope()
6
58
 
7
59
  export {
8
60
  // watch
@@ -29,27 +81,12 @@ export {
29
81
  // computed
30
82
  computed,
31
83
  // instance
32
- getCurrentInstance
33
- } from 'vue'
34
-
35
- const noop = () => {
36
- }
37
-
38
- const fixEffectScope = (scope) => {
39
- scope.pause = noop
40
- scope.resume = noop
41
- return scope
42
- }
43
-
44
- const effectScope = (detached) => fixEffectScope(vueEffectScope(detached))
45
- const getCurrentScope = () => fixEffectScope(getCurrentVueScope())
46
-
47
- export {
84
+ getCurrentInstance,
48
85
  // effectScope
49
86
  effectScope,
50
87
  getCurrentScope,
51
88
  onScopeDispose
52
- }
89
+ } from 'vue'
53
90
 
54
91
  export {
55
92
  // i18n
@@ -1,7 +1,7 @@
1
1
  import MpxProxy from '../../../core/proxy'
2
2
  import builtInKeysMap from '../builtInKeysMap'
3
3
  import mergeOptions from '../../../core/mergeOptions'
4
- import { isFunction, error, diffAndCloneA, hasOwn } from '@mpxjs/utils'
4
+ import { isFunction, error, diffAndCloneA, hasOwn, noop } from '@mpxjs/utils'
5
5
 
6
6
  function transformApiForProxy (context, currentInject) {
7
7
  const rawSetData = context.setData.bind(context)
@@ -45,16 +45,14 @@ function transformApiForProxy (context, currentInject) {
45
45
  }
46
46
  })
47
47
  if (currentInject) {
48
- if (currentInject.render) {
49
- Object.defineProperties(context, {
50
- __injectedRender: {
51
- get () {
52
- return currentInject.render.bind(context)
53
- },
54
- configurable: false
55
- }
56
- })
57
- }
48
+ Object.defineProperties(context, {
49
+ __injectedRender: {
50
+ get () {
51
+ return currentInject.render || noop
52
+ },
53
+ configurable: false
54
+ }
55
+ })
58
56
  if (currentInject.getRefsData) {
59
57
  Object.defineProperties(context, {
60
58
  __getRefsData: {
@@ -3,7 +3,7 @@ import mergeOptions from '../../../core/mergeOptions'
3
3
  import { diffAndCloneA, hasOwn } from '@mpxjs/utils'
4
4
  import { getCurrentInstance as getCurrentVueInstance } from '../../export/index'
5
5
  import MpxProxy, { setCurrentInstance, unsetCurrentInstance } from '../../../core/proxy'
6
- import { BEFORECREATE, BEFOREUPDATE, UPDATED, BEFOREUNMOUNT, UNMOUNTED } from '../../../core/innerLifecycle'
6
+ import { BEFORECREATE, BEFOREUPDATE, UPDATED, BEFOREUNMOUNT, UNMOUNTED, SERVERPREFETCH } from '../../../core/innerLifecycle'
7
7
 
8
8
  function filterOptions (options) {
9
9
  const newOptions = {}
@@ -79,6 +79,9 @@ export function getDefaultOptions (type, { rawOptions = {} }) {
79
79
  },
80
80
  destroyed () {
81
81
  if (this.__mpxProxy) this.__mpxProxy.callHook(UNMOUNTED)
82
+ },
83
+ serverPrefetch () {
84
+ if (this.__mpxProxy) return this.__mpxProxy.callHook(SERVERPREFETCH)
82
85
  }
83
86
  }]
84
87
  // 为了在builtMixin中可以使用某些rootMixin实现的特性(如数据响应等),此处builtInMixin在rootMixin之后执行,但是当builtInMixin使用存在对应内建生命周期的目标平台声明周期写法时,可能会出现用户生命周期比builtInMixin中的生命周期先执行的情况,为了避免这种情况发生,builtInMixin应该尽可能使用内建生命周期来编写
@@ -9,7 +9,8 @@ const COMPONENT_HOOKS = [
9
9
  'deactivated',
10
10
  'beforeDestroy',
11
11
  'destroyed',
12
- 'errorCaptured'
12
+ 'errorCaptured',
13
+ 'serverPrefetch'
13
14
  ]
14
15
 
15
16
  const PAGE_HOOKS = [
@@ -38,7 +39,9 @@ const APP_HOOKS = [
38
39
  'onError',
39
40
  'onPageNotFound',
40
41
  'onUnhandledRejection',
41
- 'onThemeChange'
42
+ 'onThemeChange',
43
+ 'onSSRAppCreated',
44
+ 'onAppInit'
42
45
  ]
43
46
 
44
47
  export const LIFECYCLE = {
@@ -1,4 +1,4 @@
1
- import { hasOwn } from '@mpxjs/utils'
1
+ import { hasOwn, noop } from '@mpxjs/utils'
2
2
  import MpxProxy from '../../../core/proxy'
3
3
  import builtInKeysMap from '../builtInKeysMap'
4
4
  import mergeOptions from '../../../core/mergeOptions'
@@ -83,16 +83,14 @@ function transformApiForProxy (context, currentInject) {
83
83
 
84
84
  // 绑定注入的render
85
85
  if (currentInject) {
86
- if (currentInject.render) {
87
- Object.defineProperties(context, {
88
- __injectedRender: {
89
- get () {
90
- return currentInject.render
91
- },
92
- configurable: false
93
- }
94
- })
95
- }
86
+ Object.defineProperties(context, {
87
+ __injectedRender: {
88
+ get () {
89
+ return currentInject.render || noop
90
+ },
91
+ configurable: false
92
+ }
93
+ })
96
94
  if (currentInject.getRefsData) {
97
95
  Object.defineProperties(context, {
98
96
  __getRefsData: {
@@ -14,7 +14,8 @@ const APP_HOOKS = [
14
14
  'onError',
15
15
  'onPageNotFound',
16
16
  'onUnhandledRejection',
17
- 'onThemeChange'
17
+ 'onThemeChange',
18
+ 'onAppInit'
18
19
  ]
19
20
 
20
21
  const PAGE_HOOKS = [
package/src/vuePlugin.js CHANGED
@@ -1,12 +1,39 @@
1
- import { walkChildren, parseSelector, error } from '@mpxjs/utils'
2
- import * as webApi from '@mpxjs/api-proxy/src/web/api'
1
+ import { walkChildren, parseSelector, error, hasOwn } from '@mpxjs/utils'
2
+ import { createSelectorQuery, createIntersectionObserver } from '@mpxjs/api-proxy'
3
+ const datasetReg = /^data-(.+)$/
4
+
5
+ function collectDataset (attrs) {
6
+ const dataset = {}
7
+ for (const key in attrs) {
8
+ if (hasOwn(attrs, key)) {
9
+ const matched = datasetReg.exec(key)
10
+ if (matched) {
11
+ dataset[matched[1]] = attrs[key]
12
+ }
13
+ }
14
+ }
15
+ return dataset
16
+ }
3
17
 
4
18
  export default function install (Vue) {
5
19
  Vue.prototype.triggerEvent = function (eventName, eventDetail) {
6
- return this.$emit(eventName, {
20
+ // 输出Web时自定义组件绑定click事件会和web原生事件冲突,组件内部triggerEvent时会导致事件执行两次,将click事件改为_click来规避此问题
21
+ const escapeEvents = ['click']
22
+ if (escapeEvents.includes(eventName)) {
23
+ eventName = '_' + eventName
24
+ }
25
+ let eventObj = {}
26
+ const dataset = collectDataset(this.$attrs)
27
+ const id = this.$attrs.id || ''
28
+ const timeStamp = +new Date()
29
+ eventObj = {
7
30
  type: eventName,
31
+ timeStamp,
32
+ target: { id, dataset, targetDataset: dataset },
33
+ currentTarget: { id, dataset },
8
34
  detail: eventDetail
9
- })
35
+ }
36
+ return this.$emit(eventName, eventObj)
10
37
  }
11
38
  Vue.prototype.selectComponent = function (selector, all) {
12
39
  const result = []
@@ -23,9 +50,9 @@ export default function install (Vue) {
23
50
  return this.selectComponent(selector, true)
24
51
  }
25
52
  Vue.prototype.createSelectorQuery = function () {
26
- return webApi.createSelectorQuery().in(this)
53
+ return createSelectorQuery().in(this)
27
54
  }
28
55
  Vue.prototype.createIntersectionObserver = function (component, options) {
29
- return webApi.createIntersectionObserver(component, options)
56
+ return createIntersectionObserver(this, options)
30
57
  }
31
58
  }