提交 174b8325 编写于 作者: fxy060608's avatar fxy060608

fix(mp-weixin): edge case of editor ready (#3406)

上级 f11e6834
import { hyphenate } from '@vue/shared' import { hyphenate } from '@vue/shared'
import { SLOT_DEFAULT_NAME, dynamicSlotName } from '@dcloudio/uni-shared' import { SLOT_DEFAULT_NAME, dynamicSlotName } from '@dcloudio/uni-shared'
import { import {
createBindDirectiveNode,
formatMiniProgramEvent, formatMiniProgramEvent,
isDirectiveNode,
isElementNode, isElementNode,
isSimpleExpressionNode,
isUserComponent, isUserComponent,
MiniProgramCompilerOptions, MiniProgramCompilerOptions,
} from '@dcloudio/uni-cli-shared' } from '@dcloudio/uni-cli-shared'
...@@ -251,6 +254,29 @@ function genComponent(node: ComponentNode, context: TemplateCodegenContext) { ...@@ -251,6 +254,29 @@ function genComponent(node: ComponentNode, context: TemplateCodegenContext) {
return genElement(node, context) 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) { function isLazyElement(node: ElementNode, context: TemplateCodegenContext) {
if (!context.lazyElement) { if (!context.lazyElement) {
return false return false
...@@ -278,6 +304,10 @@ function isLazyElement(node: ElementNode, context: TemplateCodegenContext) { ...@@ -278,6 +304,10 @@ function isLazyElement(node: ElementNode, context: TemplateCodegenContext) {
*/ */
function genLazyElement(node: ElementNode, context: TemplateCodegenContext) { function genLazyElement(node: ElementNode, context: TemplateCodegenContext) {
const { push } = context const { push } = context
// TODO 目前硬编码,仅限 editor 的 ready
if (node.tag === 'editor') {
addEventHandlers(node)
}
if (!isIfElementNode(node)) { if (!isIfElementNode(node)) {
push(`<block`) push(`<block`)
// r0 => ready 首次渲染 // r0 => ready 首次渲染
......
...@@ -17,6 +17,7 @@ type EventValue = Function | Function[] ...@@ -17,6 +17,7 @@ type EventValue = Function | Function[]
interface Invoker { interface Invoker {
(evt: MPEvent): unknown (evt: MPEvent): unknown
id: string
value: EventValue value: EventValue
} }
...@@ -49,8 +50,10 @@ export function vOn(value: EventValue | undefined, key?: number | string) { ...@@ -49,8 +50,10 @@ export function vOn(value: EventValue | undefined, key?: number | string) {
} else { } else {
// add // add
mpInstance[name] = createInvoker( mpInstance[name] = createInvoker(
name,
value, value,
instance as unknown as ComponentInternalInstance instance as unknown as ComponentInternalInstance,
mpInstance
) )
} }
return name return name
...@@ -65,15 +68,26 @@ export interface MPEvent extends WechatMiniprogram.BaseEvent { ...@@ -65,15 +68,26 @@ export interface MPEvent extends WechatMiniprogram.BaseEvent {
stopImmediatePropagation: () => void stopImmediatePropagation: () => void
} }
const editorReady = 'eReady'
function createInvoker( function createInvoker(
name: string,
initialValue: EventValue, initialValue: EventValue,
instance: ComponentInternalInstance | null instance: ComponentInternalInstance | null,
mpInstance: Record<string, any>
) { ) {
const invoker: Invoker = (e: MPEvent) => { 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) patchMPEvent(e)
let args: unknown[] = [e] let args: unknown[] = [e]
if ((e as MPEvent).detail && (e as MPEvent).detail.__args__) { if (e.detail && e.detail.__args__) {
args = (e as MPEvent).detail.__args__! args = e.detail.__args__!
} }
const eventValue = invoker.value const eventValue = invoker.value
const invoke = () => const invoke = () =>
...@@ -85,18 +99,14 @@ function createInvoker( ...@@ -85,18 +99,14 @@ function createInvoker(
) )
// 冒泡事件触发时,启用延迟策略,避免同一批次的事件执行时机不正确,对性能可能有略微影响 https://github.com/dcloudio/uni-app/issues/3228 // 冒泡事件触发时,启用延迟策略,避免同一批次的事件执行时机不正确,对性能可能有略微影响 https://github.com/dcloudio/uni-app/issues/3228
const eventTarget = (e as MPEvent).target const eventSync = dataset && dataset.eventsync
const eventSync = eventTarget
? eventTarget.dataset
? eventTarget.dataset.eventsync === 'true'
: false
: false
if (bubbles.includes(e.type) && !eventSync) { if (bubbles.includes(e.type) && !eventSync) {
setTimeout(invoke) setTimeout(invoke)
} else { } else {
return invoke() return invoke()
} }
} }
invoker.id = name
invoker.value = initialValue invoker.value = initialValue
return invoker return invoker
} }
......
...@@ -60,21 +60,21 @@ describe('mp-weixin: transform component', () => { ...@@ -60,21 +60,21 @@ describe('mp-weixin: transform component', () => {
) )
assert( assert(
`<editor @ready="ready"/>`, `<editor @ready="ready"/>`,
`<block wx:if="{{r0}}"><editor bindready="{{a}}"/></block>`, `<block wx:if="{{r0}}"><editor bindready="{{a}}" data-e-ready="{{a}}"/></block>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _o(_ctx.ready) } return { a: _o(_ctx.ready) }
}` }`
) )
assert( assert(
`<editor v-if="ok1" @ready="ready"/><editor v-else-if="ok2"/><editor v-else/>`, `<editor v-if="ok1" @ready="ready"/><editor v-else-if="ok2"/><editor v-else/>`,
`<editor wx:if="{{a}}" bindready="{{b}}"/><editor wx:elif="{{c}}"/><editor wx:else/>`, `<editor wx:if="{{a}}" bindready="{{b}}" data-e-ready="{{b}}"/><editor wx:elif="{{c}}"/><editor wx:else/>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return _e({ a: _ctx.ok1 }, _ctx.ok1 ? { b: _o(_ctx.ready) } : _ctx.ok2 ? {} : {}, { c: _ctx.ok2 }) return _e({ a: _ctx.ok1 }, _ctx.ok1 ? { b: _o(_ctx.ready) } : _ctx.ok2 ? {} : {}, { c: _ctx.ok2 })
}` }`
) )
assert( assert(
`<editor v-if="ok1" @ready="ready"/><editor v-else-if="ok2"/><editor v-else @ready="ready"/>`, `<editor v-if="ok1" @ready="ready"/><editor v-else-if="ok2"/><editor v-else @ready="ready"/>`,
`<editor wx:if="{{a}}" bindready="{{b}}"/><editor wx:elif="{{c}}"/><block wx:else><editor wx:if="{{r0}}" bindready="{{d}}"/></block>`, `<editor wx:if="{{a}}" bindready="{{b}}" data-e-ready="{{b}}"/><editor wx:elif="{{c}}"/><block wx:else><editor wx:if="{{r0}}" bindready="{{d}}" data-e-ready="{{d}}"/></block>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return _e({ a: _ctx.ok1 }, _ctx.ok1 ? { b: _o(_ctx.ready) } : _ctx.ok2 ? {} : { d: _o(_ctx.ready) }, { c: _ctx.ok2 }) return _e({ a: _ctx.ok1 }, _ctx.ok1 ? { b: _o(_ctx.ready) } : _ctx.ok2 ? {} : { d: _o(_ctx.ready) }, { c: _ctx.ok2 })
}` }`
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册