提交 96443dee 编写于 作者: Q qiang

fix: 解决v-for中方法使用复杂表达式报错的问题 fixed #373

上级 68cd6c67
......@@ -326,6 +326,12 @@ describe('mp:compiler', () => {
'<input @input="onInput($event, 2+2);">',
'<input data-event-opts="{{[[\'input\',[[\'onInput\',[\'$event\',2+2]]]]]}}" bindinput="__e"/>'
)
// v-for
assertCodegen(
'<view v-for="(item,index) in list" :key="index"><view @click="$test.test(item)">test</view></view>',
'<block wx:for="{{list}}" wx:for-item="item" wx:for-index="index" wx:key="index"><view><view data-event-opts="{{[[\'tap\',[[\'e0\',[\'$event\']]]]]}}" data-event-params="{{[{item}]}}" bindtap="__e">test</view></view></block>',
'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(
// `<input @input="onInput(');[\\'());');">`,
......
......@@ -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$$__'
}
}
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
}
......@@ -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) &&
......
......@@ -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])))
}
})
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册