diff --git a/packages/uni-template-compiler/__tests__/compiler.spec.js b/packages/uni-template-compiler/__tests__/compiler.spec.js
index ffe3352f7d72ec8869e989478761069a83a46887..dc9dc5aac9a0cefdefd7ff1bd323ec648055e9a1 100644
--- a/packages/uni-template-compiler/__tests__/compiler.spec.js
+++ b/packages/uni-template-compiler/__tests__/compiler.spec.js
@@ -326,6 +326,12 @@ describe('mp:compiler', () => {
'',
''
)
+ // v-for
+ assertCodegen(
+ 'test',
+ 'test',
+ 'with(this){if(!_isMounted){e0=function($event,item){var _temp=arguments[arguments.length-1].currentTarget.dataset,_temp2=(_temp.eventParams||_temp["event-params"])[0],item=_temp2.item;var _temp,_temp2;return $test.test(item)}}}'
+ )
// tricky symbols in args
// assertCodegen(
// ``,
diff --git a/packages/uni-template-compiler/lib/constants.js b/packages/uni-template-compiler/lib/constants.js
index 4597c3a33f28c5ab1454155ed8269e6b553e89b7..885ee953b3049c402e397edd5e3798a1564fa313 100644
--- a/packages/uni-template-compiler/lib/constants.js
+++ b/packages/uni-template-compiler/lib/constants.js
@@ -62,6 +62,7 @@ module.exports = {
VAR_FILTER: 'F',
ATTR_DATA_EVENT_OPTS: 'data-event-opts',
ATTR_DATA_COM_TYPE: 'data-com-type',
+ ATTR_DATA_EVENT_PARAMS: 'data-event-params',
INTERNAL_GET_ORIG,
INTERNAL_GET_CLASS,
INTERNAL_GET_STYLE,
@@ -120,4 +121,4 @@ module.exports = {
IDENTIFIER_STYLE: '__$$style$$__',
IDENTIFIER_EVENT: '__$$event$$__',
IDENTIFIER_GLOBAL: '__$$global$$__'
-}
+}
diff --git a/packages/uni-template-compiler/lib/script/traverse/data/event.js b/packages/uni-template-compiler/lib/script/traverse/data/event.js
index c1dccb98a83d8847ea38ad9d033dca8a95953264..bbb42c8b2674a9c08954f1eff12e4dbe9888b4e3 100644
--- a/packages/uni-template-compiler/lib/script/traverse/data/event.js
+++ b/packages/uni-template-compiler/lib/script/traverse/data/event.js
@@ -1,10 +1,12 @@
const t = require('@babel/types')
+const parser = require('@babel/parser')
const {
IDENTIFIER_EVENT,
VUE_EVENT_MODIFIERS,
INTERNAL_EVENT_PROXY,
ATTR_DATA_EVENT_OPTS,
+ ATTR_DATA_EVENT_PARAMS,
INTERNAL_SET_SYNC
} = require('../../../constants')
@@ -212,8 +214,9 @@ function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false,
let isOnce = false
const methods = []
+ const params = []
- if (type) {
+ if (type) {
isPassive = type.charAt(0) === VUE_EVENT_MODIFIERS.passive
type = isPassive ? type.slice(1) : type
@@ -318,7 +321,7 @@ function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false,
ReturnStatement (path) {
const argument = path.node.argument
if (t.isCallExpression(argument)) {
- if (t.isIdentifier(argument.callee)) {
+ if (t.isIdentifier(argument.callee)) { // || t.isMemberExpression(argument.callee)
anonymous = false
parseEventByCallExpression(argument, methods)
}
@@ -326,6 +329,27 @@ function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false,
}
})
if (anonymous) {
+ // 处理复杂表达式中使用的局部变量(主要在v-for中定义)
+ funcPath.traverse({
+ Identifier (path) {
+ const scope = path.scope
+ const node = path.node
+ const name = node.name
+ if (path.key !== 'key' && path.key !== 'property' && scope && !scope.hasOwnBinding(name) && scope.hasBinding(name)) {
+ params.push(name)
+ }
+ }
+ })
+ params.forEach(name => {
+ funcPath.node.params.push(t.identifier(name))
+ })
+ if (params.length) {
+ const datasetUid = funcPath.scope.generateDeclaredUidIdentifier().name
+ const paramsUid = funcPath.scope.generateDeclaredUidIdentifier().name
+ const dataset = ATTR_DATA_EVENT_PARAMS.substring(5)
+ const code = `var ${datasetUid}=arguments[arguments.length-1].currentTarget.dataset,${paramsUid}=(${datasetUid}.${dataset.replace(/-([a-z])/, (_, str) => str.toUpperCase())}||${datasetUid}['${dataset}'])[0],${params.map(item => `${item}=${paramsUid}.${item}`).join(',')}`
+ funcPath.node.body.body.unshift(parser.parse(code).program.body[0])
+ }
methods.push(addEventExpressionStatement(funcPath, state, isComponent, isNativeOn))
}
}
@@ -334,6 +358,7 @@ function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false,
return {
type,
+ params,
methods,
modifiers: {
isCatch,
@@ -358,6 +383,7 @@ function _processEvent (path, state, isComponent, isNativeOn = false, tagName, r
const valuePath = propertyPath.get('value')
const {
type,
+ params,
methods,
modifiers: {
isCatch,
@@ -393,12 +419,13 @@ function _processEvent (path, state, isComponent, isNativeOn = false, tagName, r
if (isCustom) {
optType = VUE_EVENT_MODIFIERS.custom + optType
}
- opts.push(
- t.arrayExpression([
+ opts.push({
+ opt: t.arrayExpression([
t.stringLiteral(optType),
t.arrayExpression(methods)
- ])
- )
+ ]),
+ params
+ })
keyPath.replaceWith(
t.stringLiteral(
@@ -422,15 +449,18 @@ module.exports = function processEvent (paths, path, state, isComponent, tagName
const ret = []
const opts = []
+ const params = []
if (onPath) {
- _processEvent(onPath, state, isComponent, false, tagName, ret).forEach(opt => {
+ _processEvent(onPath, state, isComponent, false, tagName, ret).forEach(({ opt, params: array }) => {
opts.push(opt)
+ params.push(...array)
})
}
if (nativeOnPath) {
- _processEvent(nativeOnPath, state, isComponent, true, tagName, ret).forEach(opt => {
+ _processEvent(nativeOnPath, state, isComponent, true, tagName, ret).forEach(({ opt, params: array }) => {
opts.push(opt)
+ params.push(...array)
})
}
if (!opts.length) {
@@ -444,5 +474,15 @@ module.exports = function processEvent (paths, path, state, isComponent, tagName
)
)
+ if (params.length) {
+ ret.push(
+ t.objectProperty(
+ t.stringLiteral(ATTR_DATA_EVENT_PARAMS),
+ // 使用数组格式,直接使用对象格式微信小程序编译会报错
+ t.stringLiteral(`{{[{${params.join(',')}}]}}`)
+ )
+ )
+ }
+
return ret
}
diff --git a/packages/uni-template-compiler/lib/script/traverse/visitor.js b/packages/uni-template-compiler/lib/script/traverse/visitor.js
index 5a81060f39a7e20260f23a87d92fa04569d17cff..6f41068ccc289be09072a2c27e4ed880c5f51c8f 100644
--- a/packages/uni-template-compiler/lib/script/traverse/visitor.js
+++ b/packages/uni-template-compiler/lib/script/traverse/visitor.js
@@ -132,7 +132,7 @@ function checkUsingGlobalComponents (name, globalUsingComponents, state) {
}
module.exports = {
- noScope: true,
+ noScope: false,
MemberExpression (path) {
if ( // t.m(123)
t.isIdentifier(path.node.object) &&
diff --git a/src/core/runtime/wrapper/util.js b/src/core/runtime/wrapper/util.js
index be9f757528e5bbc21e566d0eeae91a5cc0eebf00..f826a183effbf7f83315ffb1817a50bf095b52e5 100644
--- a/src/core/runtime/wrapper/util.js
+++ b/src/core/runtime/wrapper/util.js
@@ -542,14 +542,17 @@ export function handleEvent (event) {
}
handler.once = true
}
- ret.push(handler.apply(handlerCtx, processEventArgs(
+ const params = processEventArgs(
this.$vm,
event,
eventArray[1],
eventArray[2],
isCustom,
methodName
- )))
+ ) || []
+ // 参数尾部增加原始事件对象用于复杂表达式内获取额外数据
+ // eslint-disable-next-line no-sparse-arrays
+ ret.push(handler.apply(handlerCtx, params.concat([, , , , , , , , , , event])))
}
})
}