From 174b8325681eee36146563f54be9348a54aefb72 Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Fri, 8 Apr 2022 11:15:30 +0800 Subject: [PATCH] fix(mp-weixin): edge case of editor ready (#3406) --- .../uni-mp-compiler/src/template/codegen.ts | 30 +++++++++++++++++++ packages/uni-mp-vue/src/helpers/vOn.ts | 30 ++++++++++++------- .../uni-mp-weixin/__tests__/component.spec.ts | 6 ++-- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/packages/uni-mp-compiler/src/template/codegen.ts b/packages/uni-mp-compiler/src/template/codegen.ts index a9f2aa632..9a7ed1ec5 100644 --- a/packages/uni-mp-compiler/src/template/codegen.ts +++ b/packages/uni-mp-compiler/src/template/codegen.ts @@ -1,8 +1,11 @@ import { hyphenate } from '@vue/shared' import { SLOT_DEFAULT_NAME, dynamicSlotName } from '@dcloudio/uni-shared' import { + createBindDirectiveNode, formatMiniProgramEvent, + isDirectiveNode, isElementNode, + isSimpleExpressionNode, isUserComponent, MiniProgramCompilerOptions, } from '@dcloudio/uni-cli-shared' @@ -251,6 +254,29 @@ function genComponent(node: ComponentNode, context: TemplateCodegenContext) { return genElement(node, context) } +function genEventHandlerAttr(type: string) { + return `data-e-` + type +} + +function addEventHandlers({ props }: ElementNode) { + props.forEach((prop) => { + if (!isDirectiveNode(prop)) { + return + } + const { name, arg, exp } = prop + if (name !== 'on' || !arg || !exp) { + return + } + if (!isSimpleExpressionNode(arg) || !isSimpleExpressionNode(exp)) { + return + } + // TODO 目前硬编码,仅限ready + if (arg.content === 'ready') { + props.push(createBindDirectiveNode(genEventHandlerAttr(arg.content), exp)) + } + }) +} + function isLazyElement(node: ElementNode, context: TemplateCodegenContext) { if (!context.lazyElement) { return false @@ -278,6 +304,10 @@ function isLazyElement(node: ElementNode, context: TemplateCodegenContext) { */ function genLazyElement(node: ElementNode, context: TemplateCodegenContext) { const { push } = context + // TODO 目前硬编码,仅限 editor 的 ready + if (node.tag === 'editor') { + addEventHandlers(node) + } if (!isIfElementNode(node)) { push(` ready 首次渲染 diff --git a/packages/uni-mp-vue/src/helpers/vOn.ts b/packages/uni-mp-vue/src/helpers/vOn.ts index ee63b99b0..fb97e3292 100644 --- a/packages/uni-mp-vue/src/helpers/vOn.ts +++ b/packages/uni-mp-vue/src/helpers/vOn.ts @@ -17,6 +17,7 @@ type EventValue = Function | Function[] interface Invoker { (evt: MPEvent): unknown + id: string value: EventValue } @@ -49,8 +50,10 @@ export function vOn(value: EventValue | undefined, key?: number | string) { } else { // add mpInstance[name] = createInvoker( + name, value, - instance as unknown as ComponentInternalInstance + instance as unknown as ComponentInternalInstance, + mpInstance ) } return name @@ -65,15 +68,26 @@ export interface MPEvent extends WechatMiniprogram.BaseEvent { stopImmediatePropagation: () => void } +const editorReady = 'eReady' + function createInvoker( + name: string, initialValue: EventValue, - instance: ComponentInternalInstance | null + instance: ComponentInternalInstance | null, + mpInstance: Record ) { const invoker: Invoker = (e: MPEvent) => { + const dataset = e.target && e.target.dataset + // TODO 临时解决 editor ready 事件可能错乱的问题 https://github.com/dcloudio/uni-app/issues/3406 + if (mpInstance && dataset && dataset[editorReady]) { + if (invoker.id !== dataset[editorReady]) { + return mpInstance[dataset[editorReady]](e) + } + } patchMPEvent(e) let args: unknown[] = [e] - if ((e as MPEvent).detail && (e as MPEvent).detail.__args__) { - args = (e as MPEvent).detail.__args__! + if (e.detail && e.detail.__args__) { + args = e.detail.__args__! } const eventValue = invoker.value const invoke = () => @@ -85,18 +99,14 @@ function createInvoker( ) // 冒泡事件触发时,启用延迟策略,避免同一批次的事件执行时机不正确,对性能可能有略微影响 https://github.com/dcloudio/uni-app/issues/3228 - const eventTarget = (e as MPEvent).target - const eventSync = eventTarget - ? eventTarget.dataset - ? eventTarget.dataset.eventsync === 'true' - : false - : false + const eventSync = dataset && dataset.eventsync if (bubbles.includes(e.type) && !eventSync) { setTimeout(invoke) } else { return invoke() } } + invoker.id = name invoker.value = initialValue return invoker } diff --git a/packages/uni-mp-weixin/__tests__/component.spec.ts b/packages/uni-mp-weixin/__tests__/component.spec.ts index 738120eaa..233a1c70d 100644 --- a/packages/uni-mp-weixin/__tests__/component.spec.ts +++ b/packages/uni-mp-weixin/__tests__/component.spec.ts @@ -60,21 +60,21 @@ describe('mp-weixin: transform component', () => { ) assert( ``, - ``, + ``, `(_ctx, _cache) => { return { a: _o(_ctx.ready) } }` ) assert( ``, - ``, + ``, `(_ctx, _cache) => { return _e({ a: _ctx.ok1 }, _ctx.ok1 ? { b: _o(_ctx.ready) } : _ctx.ok2 ? {} : {}, { c: _ctx.ok2 }) }` ) assert( ``, - ``, + ``, `(_ctx, _cache) => { return _e({ a: _ctx.ok1 }, _ctx.ok1 ? { b: _o(_ctx.ready) } : _ctx.ok2 ? {} : { d: _o(_ctx.ready) }, { c: _ctx.ok2 }) }` -- GitLab