diff --git a/packages/uni-mp-baidu/__tests__/testUtils.ts b/packages/uni-mp-baidu/__tests__/testUtils.ts
index a8e9f1dd98fa6f9d8d7cd9735b91aafcdb00fbe9..6e314b67c1552df1e77308f65b1fcf316b402a03 100644
--- a/packages/uni-mp-baidu/__tests__/testUtils.ts
+++ b/packages/uni-mp-baidu/__tests__/testUtils.ts
@@ -1,6 +1,7 @@
import { isCustomElement, isNativeTag } from '@dcloudio/uni-shared'
import { compile, CompilerOptions } from '@dcloudio/uni-mp-compiler'
import { transformFor } from '../src/plugin/transforms/vFor'
+import { transformOn } from '../src/plugin/transforms/vOn'
export function assert(
template: string,
@@ -19,6 +20,9 @@ export function assert(
concise: true,
},
nodeTransforms: [transformFor],
+ directiveTransforms: {
+ on: transformOn,
+ },
miniProgram: {
slot: {
fallback: false,
diff --git a/packages/uni-mp-baidu/__tests__/vOn.spec.ts b/packages/uni-mp-baidu/__tests__/vOn.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..baddb5a98aa6586de71468a3d65e4438ebe81dfd
--- /dev/null
+++ b/packages/uni-mp-baidu/__tests__/vOn.spec.ts
@@ -0,0 +1,33 @@
+import { assert } from './testUtils'
+
+describe('mp-baidu: transform v-on', () => {
+ describe('component', () => {
+ test(`built-in event`, () => {
+ assert(
+ ``,
+ ``,
+ `(_ctx, _cache) => {
+ return { a: _o(_ctx.tap) }
+}`
+ )
+ })
+ test(`custom event`, () => {
+ assert(
+ ``,
+ ``,
+ `(_ctx, _cache) => {
+ return { a: { 'click': _o(_ctx.click) } }
+}`
+ )
+ }),
+ test(`multi custom event`, () => {
+ assert(
+ ``,
+ ``,
+ `(_ctx, _cache) => {
+ return { a: { 'custom-mount': _o($event => { _ctx.mount(); _ctx.created(); }), 'unmount': _o(_ctx.unmount) } }
+}`
+ )
+ })
+ })
+})
diff --git a/packages/uni-mp-baidu/dist/uni.compiler.js b/packages/uni-mp-baidu/dist/uni.compiler.js
index deaf2feccc9f7cc637e22ba69079a86a1885436e..1e0ba665816a33f02104e9192c0313b58e93e858 100644
--- a/packages/uni-mp-baidu/dist/uni.compiler.js
+++ b/packages/uni-mp-baidu/dist/uni.compiler.js
@@ -3,6 +3,7 @@
var uniCliShared = require('@dcloudio/uni-cli-shared');
var initMiniProgramPlugin = require('@dcloudio/uni-mp-vite');
var uniMpCompiler = require('@dcloudio/uni-mp-compiler');
+var compilerCore = require('@vue/compiler-core');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -48,6 +49,74 @@ const transformFor = (node) => {
}
};
+/**
+ * 百度小程序的自定义组件,不支持动态事件绑定,故转换为静态事件 + dataset
+ * @param dir
+ * @param node
+ * @param context
+ * @param augmentor
+ * @returns
+ */
+const transformOn = (dir, node, context, augmentor) => {
+ const res = uniMpCompiler.transformOn(dir, node, context, augmentor);
+ const { name, arg, exp } = dir;
+ if (name !== 'on' ||
+ !arg ||
+ !exp ||
+ !compilerCore.isStaticExp(arg) ||
+ !isCustomEvent(arg.content) ||
+ !uniMpCompiler.isUserComponent(node, context)) {
+ return res;
+ }
+ // data-event-opts
+ const opts = compilerCore.findProp(node, ATTR_DATA_EVENT_OPTS, true);
+ const value = res.props[0].value;
+ res.props[0].value = compilerCore.createSimpleExpression('__e', true);
+ if (!opts) {
+ node.props.push(createDataEventOptsProp(arg.content, value));
+ }
+ else {
+ const children = opts.exp.children;
+ children.splice(children.length - 2, 0, createDataEventOptsProperty(arg.content, value));
+ }
+ return res;
+};
+const ATTR_DATA_EVENT_OPTS = 'data-e-o';
+function createDataEventOptsProperty(event, exp) {
+ return compilerCore.createCompoundExpression([`'${event}'`, ': ', exp, ',']);
+}
+function createDataEventOptsProp(event, exp) {
+ return {
+ type: 7 /* DIRECTIVE */,
+ name: 'bind',
+ loc: compilerCore.locStub,
+ modifiers: [],
+ arg: compilerCore.createSimpleExpression(ATTR_DATA_EVENT_OPTS, true),
+ exp: compilerCore.createCompoundExpression([
+ '{',
+ createDataEventOptsProperty(event, exp),
+ '}',
+ ]),
+ };
+}
+const builtInEvents = [
+ 'tap',
+ 'longtap',
+ 'longpress',
+ 'touchstart',
+ 'touchmove',
+ 'touchcancel',
+ 'touchend',
+ 'touchforcechange',
+ 'transitionend',
+ 'animationstart',
+ 'animationiteration',
+ 'animationend',
+];
+function isCustomEvent(name) {
+ return !builtInEvents.includes(name);
+}
+
const uniMiniProgramBaiduPlugin = {
name: 'vite:uni-mp-baidu',
config() {
@@ -103,6 +172,9 @@ ${filter.code}
directive: 's-',
compilerOptions: {
nodeTransforms: [transformFor],
+ directiveTransforms: {
+ on: transformOn,
+ },
},
},
style: {
diff --git a/packages/uni-mp-baidu/dist/uni.mp.esm.js b/packages/uni-mp-baidu/dist/uni.mp.esm.js
index b1d1fe69b99f8989f1804279308df086b1e7e950..dbc450c0c2ade9d9352c6120067610b5da576f97 100644
--- a/packages/uni-mp-baidu/dist/uni.mp.esm.js
+++ b/packages/uni-mp-baidu/dist/uni.mp.esm.js
@@ -871,6 +871,15 @@ function parse$1(componentOptions) {
__l: methods.__l,
};
delete methods.__l;
+ methods.__e = handleCustomEvent;
+}
+function handleCustomEvent(event) {
+ const { type, target: { dataset: { eO: eventOpts }, }, } = event;
+ const methodName = (eventOpts || {})[type];
+ if (!methodName) {
+ return console.warn(type + ' not found');
+ }
+ this[methodName](event);
}
var parseComponentOptions = /*#__PURE__*/Object.freeze({
diff --git a/packages/uni-mp-baidu/src/plugin/index.ts b/packages/uni-mp-baidu/src/plugin/index.ts
index c8c363cb11bf289fcc48ebf410fb361ad8ebb225..52ab8177b38175ea79068f0b1f74940fd063f756 100644
--- a/packages/uni-mp-baidu/src/plugin/index.ts
+++ b/packages/uni-mp-baidu/src/plugin/index.ts
@@ -6,6 +6,7 @@ import initMiniProgramPlugin, {
import source from './project.swan.json'
import { transformFor } from './transforms/vFor'
+import { transformOn } from './transforms/vOn'
const uniMiniProgramBaiduPlugin: Plugin = {
name: 'vite:uni-mp-baidu',
@@ -66,6 +67,9 @@ ${filter.code}
directive: 's-',
compilerOptions: {
nodeTransforms: [transformFor],
+ directiveTransforms: {
+ on: transformOn,
+ },
},
},
style: {
diff --git a/packages/uni-mp-baidu/src/plugin/transforms/vOn.ts b/packages/uni-mp-baidu/src/plugin/transforms/vOn.ts
new file mode 100644
index 0000000000000000000000000000000000000000..afdf67ac41c55ed42d920346bab1195a782e48e2
--- /dev/null
+++ b/packages/uni-mp-baidu/src/plugin/transforms/vOn.ts
@@ -0,0 +1,101 @@
+import {
+ DirectiveTransform,
+ isUserComponent,
+ transformOn as baseTransformOn,
+} from '@dcloudio/uni-mp-compiler'
+import {
+ ExpressionNode,
+ DirectiveNode,
+ findProp,
+ isStaticExp,
+ NodeTypes,
+ locStub,
+ createSimpleExpression,
+ createCompoundExpression,
+ CompoundExpressionNode,
+} from '@vue/compiler-core'
+/**
+ * 百度小程序的自定义组件,不支持动态事件绑定,故转换为静态事件 + dataset
+ * @param dir
+ * @param node
+ * @param context
+ * @param augmentor
+ * @returns
+ */
+export const transformOn: DirectiveTransform = (
+ dir,
+ node,
+ context,
+ augmentor
+) => {
+ const res = baseTransformOn(dir, node, context, augmentor)
+ const { name, arg, exp } = dir
+ if (
+ name !== 'on' ||
+ !arg ||
+ !exp ||
+ !isStaticExp(arg) ||
+ !isCustomEvent(arg.content) ||
+ !isUserComponent(node, context)
+ ) {
+ return res
+ }
+ // data-event-opts
+ const opts = findProp(node, ATTR_DATA_EVENT_OPTS, true) as DirectiveNode
+ const value = res.props[0].value as ExpressionNode
+ res.props[0].value = createSimpleExpression('__e', true)
+ if (!opts) {
+ node.props.push(createDataEventOptsProp(arg.content, value))
+ } else {
+ const children = (opts.exp as CompoundExpressionNode).children
+ children.splice(
+ children.length - 2,
+ 0,
+ createDataEventOptsProperty(arg.content, value)
+ )
+ }
+ return res
+}
+
+const ATTR_DATA_EVENT_OPTS = 'data-e-o'
+
+function createDataEventOptsProperty(event: string, exp: ExpressionNode) {
+ return createCompoundExpression([`'${event}'`, ': ', exp, ','])
+}
+
+function createDataEventOptsProp(
+ event: string,
+ exp: ExpressionNode
+): DirectiveNode {
+ return {
+ type: NodeTypes.DIRECTIVE,
+ name: 'bind',
+ loc: locStub,
+ modifiers: [],
+ arg: createSimpleExpression(ATTR_DATA_EVENT_OPTS, true),
+ exp: createCompoundExpression([
+ '{',
+ createDataEventOptsProperty(event, exp),
+ '}',
+ ]),
+ }
+}
+
+const builtInEvents = [
+ 'tap',
+ 'longtap',
+ 'longpress',
+ 'touchstart',
+ 'touchmove',
+ 'touchcancel',
+ 'touchend',
+ 'touchforcechange',
+ 'transitionend',
+ 'animationstart',
+ 'animationiteration',
+ 'animationend',
+]
+
+function isCustomEvent(name: string) {
+ return !builtInEvents.includes(name)
+}
diff --git a/packages/uni-mp-baidu/src/runtime/parseComponentOptions.ts b/packages/uni-mp-baidu/src/runtime/parseComponentOptions.ts
index 0d11ebdbbb5a2a7462b278ee205b13b5a496ce63..ba629137fbe0169464aaa168419276284811b750 100644
--- a/packages/uni-mp-baidu/src/runtime/parseComponentOptions.ts
+++ b/packages/uni-mp-baidu/src/runtime/parseComponentOptions.ts
@@ -10,6 +10,7 @@ import {
fixSetDataStart,
fixSetDataEnd,
} from '../../../uni-mp-weixin/src/runtime/fixSetData'
+import { ComponentPublicInstance } from 'vue'
export { handleLink, initLifetimes } from '@dcloudio/uni-mp-weixin'
@@ -83,4 +84,29 @@ export function parse(componentOptions: MPComponentOptions) {
__l: methods.__l,
}
delete methods.__l
+
+ methods.__e = handleCustomEvent
+}
+
+function handleCustomEvent(
+ this: MPComponentInstance,
+ event: {
+ type: string
+ target: { dataset: { eO: { [name: string]: string } } }
+ detail: {
+ __args__: any[]
+ }
+ }
+) {
+ const {
+ type,
+ target: {
+ dataset: { eO: eventOpts },
+ },
+ } = event
+ const methodName = (eventOpts || {})[type]
+ if (!methodName) {
+ return console.warn(type + ' not found')
+ }
+ ;(this as any)[methodName](event)
}
diff --git a/packages/uni-mp-compiler/src/compile.ts b/packages/uni-mp-compiler/src/compile.ts
index 0f44279c9ccc845ce39bea7ce00be8a30cfecad3..6caf7af27cb9af3a6165d7a944d6740bcde4af21 100644
--- a/packages/uni-mp-compiler/src/compile.ts
+++ b/packages/uni-mp-compiler/src/compile.ts
@@ -38,7 +38,10 @@ export function getBaseTransformPreset({
if (prefixIdentifiers) {
nodeTransforms.push(transformExpression)
}
- return [nodeTransforms, { on: transformOn, bind: transformBind }]
+ return [
+ nodeTransforms,
+ { on: transformOn as unknown as DirectiveTransform, bind: transformBind },
+ ]
}
export function baseCompile(template: string, options: CompilerOptions = {}) {
diff --git a/packages/uni-mp-compiler/src/index.ts b/packages/uni-mp-compiler/src/index.ts
index 7f19ceebe3d4765508ef8d7894ebc460b40f5b4c..bc65fa38654e4d6c1001c8cca5b22c234d209985 100644
--- a/packages/uni-mp-compiler/src/index.ts
+++ b/packages/uni-mp-compiler/src/index.ts
@@ -15,13 +15,15 @@ export type {
CompilerOptions,
DirectiveNode,
NodeTransform,
+ DirectiveTransform,
TransformContext,
SimpleExpressionNode,
} from '@vue/compiler-core'
export { genExpr } from './codegen'
export { isForElementNode } from './transforms/vFor'
-
+export { isUserComponent } from './transforms/utils'
+export { transformOn } from './transforms/vOn'
export * from './runtimeHelpers'
export function parse(template: string, options: ParserOptions = {}): RootNode {
diff --git a/packages/uni-mp-compiler/src/transforms/utils.ts b/packages/uni-mp-compiler/src/transforms/utils.ts
index 82ed18897ed583446d4b1bc7df89f1454a761910..e88a09db0603943bb226487f179dda67425a4502 100644
--- a/packages/uni-mp-compiler/src/transforms/utils.ts
+++ b/packages/uni-mp-compiler/src/transforms/utils.ts
@@ -21,6 +21,7 @@ import {
RootNode,
SourceLocation,
TemplateChildNode,
+ TransformContext as VueTransformContext,
} from '@vue/compiler-core'
import { walk, BaseNode } from 'estree-walker'
import { isUndefined, parseExpr } from '../ast'
@@ -36,7 +37,7 @@ export const SCOPED_SLOT_IDENTIFIER = '__SCOPED_SLOT__'
export function isUserComponent(
node: RootNode | TemplateChildNode,
- context: TransformContext
+ context: TransformContext | VueTransformContext
): node is ComponentNode {
return (
node.type === NodeTypes.ELEMENT &&
diff --git a/packages/uni-mp-compiler/src/transforms/vOn.ts b/packages/uni-mp-compiler/src/transforms/vOn.ts
index a01472c464283bac14b5cfb1c2299d2778c6b5e2..9ae434b698e81cf61980b9c38818cb17fa77190b 100644
--- a/packages/uni-mp-compiler/src/transforms/vOn.ts
+++ b/packages/uni-mp-compiler/src/transforms/vOn.ts
@@ -12,10 +12,11 @@ import {
NodeTypes,
SimpleExpressionNode,
TO_HANDLER_KEY,
+ DirectiveTransform,
} from '@vue/compiler-core'
import { camelize, toHandlerKey } from '@vue/shared'
import { V_ON } from '../runtimeHelpers'
-import { DirectiveTransform, TransformContext } from '../transform'
+import { TransformContext } from '../transform'
import { DirectiveTransformResult } from './transformElement'
import { isBuiltInIdentifier, processExpression } from './transformExpression'
@@ -35,9 +36,10 @@ export interface VOnDirectiveNode extends DirectiveNode {
export const transformOn: DirectiveTransform = (
dir,
node,
- context,
+ _context,
augmentor
) => {
+ const context = _context as unknown as TransformContext
const { loc, modifiers, arg } = dir as VOnDirectiveNode
if (!dir.exp && !modifiers.length) {
context.onError(createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc))