提交 89208a28 编写于 作者: Q qiang

fix(mp-alipay): 支付宝小程序插件中的组件支持事件监听 #2410

上级 cb83dea9
......@@ -56,7 +56,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'<credit-pay @change="onChange" @cancle="onCancle">text</credit-pay>',
'<credit-pay onChange="__e" onCancle="__e" vue-id="551070e6-1" data-event-opts="{{[[\'^change\',[[\'onChange\']]],[\'^cancle\',[[\'onCancle\']]]]}}" data-com-type="wx" ref="__r" data-event-list="onChange,onCancle" onVueInit="__l">text</credit-pay>',
'<plugin-wrapper onChange="__e" onCancle="__e" vue-id="551070e6-1" onPluginWrap="__w" data-event-opts="{{[[\'^change\',[[\'onChange\']]],[\'^cancle\',[[\'onCancle\']]]]}}" data-com-type="wx" ref="__r" data-event-list="onChange,onCancle" onVueInit="__l"><credit-pay onChange="{{\'onChange\'+\'551070e6-1\'}}" onCancle="{{\'onCancle\'+\'551070e6-1\'}}" onVueInit="__l">text</credit-pay></plugin-wrapper>',
undefined,
undefined,
{
......
......@@ -28,6 +28,7 @@ const INTERNAL_GET_EVENT = '__get_event'
const INTERNAL_GET_REFS = '__get_refs'
const INTERNAL_EVENT_PROXY = '__e'
const INTERNAL_EVENT_LINK = '__l'
const INTERNAL_EVENT_WRAP = '__w'
const ALLOWED_GLOBAL_OBJECT = [
'Math',
......@@ -72,6 +73,7 @@ module.exports = {
INTERNAL_GET_REFS,
INTERNAL_EVENT_PROXY,
INTERNAL_EVENT_LINK,
INTERNAL_EVENT_WRAP,
INTERNAL_SET_MODEL,
INTERNAL_SET_SYNC,
METHOD_BUILT_IN: [
......
const t = require('@babel/types')
const {
METHOD_CREATE_ELEMENT,
ATTR_DATA_EVENT_OPTS,
ATTR_DATA_COM_TYPE,
ATTR_DATA_EVENT_LIST
ATTR_DATA_EVENT_LIST,
ATTR_DATA_EVENT_PARAMS,
ATTE_DATA_CUSTOM_HIDDEN,
INTERNAL_EVENT_WRAP
} = require('../../../constants')
const processRef = require('./ref')
......@@ -38,7 +43,8 @@ module.exports = function traverseData (path, state, tagName) {
})
// 该组件是引入的小程序组件
if (state.options.wxComponents[tagName]) {
const wxComponent = state.options.wxComponents[tagName]
if (wxComponent) {
addAttrProperties.push(
t.objectProperty(
t.stringLiteral(ATTR_DATA_COM_TYPE),
......@@ -66,6 +72,67 @@ module.exports = function traverseData (path, state, tagName) {
t.stringLiteral(list.join(','))
)
)
if (wxComponent.startsWith('plugin://')) {
const wrapperTag = 'plugin-wrapper'
const orgPath = path.parentPath
const orgNode = orgPath.node
const args = orgNode.arguments
const orgTag = args[0]
orgTag.$mpPlugin = true
args[0] = t.stringLiteral(wrapperTag)
const orgOptions = args[1]
const orgOptionsProps = orgOptions.properties
const targetAttrs = []
const targetOptionsProps = [
t.objectProperty(t.identifier('attrs'), t.objectExpression(targetAttrs))
]
const uniAttrs = [
ATTR_DATA_EVENT_OPTS,
ATTR_DATA_COM_TYPE,
ATTR_DATA_EVENT_PARAMS,
ATTR_DATA_EVENT_LIST,
ATTE_DATA_CUSTOM_HIDDEN,
'vue-id'
]
for (let a = orgOptionsProps.length - 1; a >= 0; a--) {
const prop = orgOptionsProps[a]
if (prop.key.name === 'attrs') {
const attrs = prop.value.properties
for (let b = attrs.length - 1; b >= 0; b--) {
const element = attrs[b]
const key = element.key.value
if (!uniAttrs.includes(key)) {
attrs.splice(b, 1)
targetAttrs.push(element)
}
}
attrs.push(t.objectProperty(t.stringLiteral('onPluginWrap'), t.stringLiteral(INTERNAL_EVENT_WRAP)))
} else if (prop.key.name === 'on') {
const ons = prop.value.properties
ons.forEach(item => {
const attrs = path.node.properties.find(prop => prop.key.name === 'attrs').value.properties
const vueId = attrs.find(prop => prop.key.value === 'vue-id').value
const eventName = item.key.value
targetAttrs.push(t.objectProperty(t.stringLiteral(eventName), t.binaryExpression('+', t.stringLiteral(eventName), vueId)))
})
} else {
orgOptionsProps.splice(a, 1)
targetOptionsProps.push(prop)
}
}
const orgChild = args[2]
const targetOptions = t.objectExpression(targetOptionsProps)
targetOptions.$mpProcessed = true
const targetArguments = [
orgTag,
targetOptions
]
if (orgChild) {
targetArguments.push(orgChild)
}
const targetNode = t.callExpression(t.identifier(METHOD_CREATE_ELEMENT), targetArguments)
args[2] = targetNode
}
}
}
......
......@@ -167,7 +167,8 @@ module.exports = {
tagNode.value = getComponentName(hyphenate(tagName))
// 组件增加 vueId
if (this.options.platform.isComponent(tagNode.value)) {
// 跳过支付宝插件组件
if (this.options.platform.isComponent(tagNode.value) && !tagNode.$mpPlugin) {
addVueId(path, this)
}
......
......@@ -236,6 +236,42 @@ module.exports = function generateComponent (compilation, jsonpFunction = 'webpa
})
}
}
// fix mp-alipay plugin
if (process.env.UNI_PLATFORM === 'mp-alipay' && appJsonFile) {
const obj = JSON.parse(appJsonFile.source())
if (obj && obj.usingComponents && !Object.keys(obj.usingComponents).length) {
const componentName = 'plugin-wrapper'
obj.usingComponents[componentName] = `/${componentName}`
const source = JSON.stringify(obj, null, 2)
appJsonFile.source = function () {
return source
}
const files = [
{
ext: 'axml',
source: '<slot></slot>'
},
{
ext: 'js',
source: 'Component({onInit(){this.props.onPluginWrap(this)},didUnmount(){this.props.onPluginWrap(this,false)}})'
},
{
ext: 'json',
source: '{"component":true}'
}
]
files.forEach(({ ext, source }) => {
compilation.assets[`${componentName}.${ext}`] = {
size () {
return Buffer.byteLength(source, 'utf8')
},
source () {
return source
}
}
})
}
}
if (process.env.UNI_FEATURE_OBSOLETE !== 'false') {
if (lastComponents.length) {
for (const name of lastComponents) {
......
......@@ -154,6 +154,14 @@ module.exports = function generateJson (compilation) {
}
})
}
// fix mp-alipay plugin
if (process.env.UNI_PLATFORM === 'mp-alipay') {
const usingComponents = jsonObj.usingComponents || {}
if (Object.values(usingComponents).find(value => value.startsWith('plugin://'))) {
const componentName = 'plugin-wrapper'
usingComponents[componentName] = '/' + componentName
}
}
if (jsonObj.genericComponents && jsonObj.genericComponents.length) { // scoped slots
// 生成genericComponents json
......
......@@ -12,6 +12,7 @@ import {
import {
handleRef,
handleLink,
handleWrap,
initBehavior,
initRelation,
triggerEvent,
......@@ -115,6 +116,7 @@ export default function parseComponent (vueComponentOptions) {
__r: handleRef,
__e: handleEvent,
__l: handleLink,
__w: handleWrap,
triggerEvent
}
}
......@@ -126,15 +128,15 @@ export default function parseComponent (vueComponentOptions) {
componentOptions.deriveDataFromProps = createObserver()
} else {
componentOptions.didUpdate = createObserver(true)
}
if (Array.isArray(vueOptions.wxsCallMethods)) {
vueOptions.wxsCallMethods.forEach(callMethod => {
componentOptions.methods[callMethod] = function (args) {
return this.$vm[callMethod](args)
}
})
}
if (Array.isArray(vueOptions.wxsCallMethods)) {
vueOptions.wxsCallMethods.forEach(callMethod => {
componentOptions.methods[callMethod] = function (args) {
return this.$vm[callMethod](args)
}
})
}
return componentOptions
}
}
......@@ -16,6 +16,7 @@ import {
import {
handleRef,
handleLink,
handleWrap,
initBehavior,
triggerEvent,
initChildVues,
......@@ -87,6 +88,7 @@ export default function parsePage (vuePageOptions) {
__r: handleRef,
__e: handleEvent,
__l: handleLink,
__w: handleWrap,
triggerEvent
}
......
......@@ -115,7 +115,7 @@ export function handleRef (ref) {
if (ref.props['data-com-type'] === 'wx') {
const eventProps = {}
let refProps = ref.props
let eventList = refProps['data-event-list'].split(',')
const eventList = refProps['data-event-list'].split(',')
// 初始化支付宝小程序组件事件
Object.keys(refProps).forEach(key => {
if (eventList.includes(key)) {
......@@ -220,3 +220,19 @@ export const handleLink = (function () {
(this._$childVues || (this._$childVues = [])).unshift(detail)
}
})()
export const handleWrap = function (mp, destory) {
const vueId = mp.props.vueId
const list = mp.props['data-event-list'].split(',')
list.forEach(eventName => {
const key = `${eventName}${vueId}`
if (destory) {
delete this[key]
} else {
// TODO remove handleRef
this[key] = function () {
mp.props[eventName].apply(this, arguments)
}
}
})
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册