提交 7c3876c1 编写于 作者: fxy060608's avatar fxy060608

wip(mp): mp-baidu

上级 7033a52e
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,
......
import { assert } from './testUtils'
describe('mp-baidu: transform v-on', () => {
describe('component', () => {
test(`built-in event`, () => {
assert(
`<custom @tap="tap"/>`,
`<custom bindtap="{{a}}" v-i="2a9ec0b0-0"/>`,
`(_ctx, _cache) => {
return { a: _o(_ctx.tap) }
}`
)
})
test(`custom event`, () => {
assert(
`<custom @click="click"/>`,
`<custom bindclick="__e" v-i="2a9ec0b0-0" data-e-o="{{a}}"/>`,
`(_ctx, _cache) => {
return { a: { 'click': _o(_ctx.click) } }
}`
)
}),
test(`multi custom event`, () => {
assert(
`<custom @unmount="unmount" @custom-mount="mount();created();"/>`,
`<custom bindunmount="__e" bind:custom-mount="__e" v-i="2a9ec0b0-0" data-e-o="{{a}}"/>`,
`(_ctx, _cache) => {
return { a: { 'custom-mount': _o($event => { _ctx.mount(); _ctx.created(); }), 'unmount': _o(_ctx.unmount) } }
}`
)
})
})
})
......@@ -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: {
......
......@@ -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({
......
......@@ -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: {
......
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)
}
......@@ -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)
}
......@@ -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 = {}) {
......
......@@ -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 {
......
......@@ -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 &&
......
......@@ -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))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册