diff --git a/packages/uni-template-compiler/__tests__/compiler-mp-alipay.spec.js b/packages/uni-template-compiler/__tests__/compiler-mp-alipay.spec.js
index 72e063b39dc96837f3253daa070fecbeb673b07a..47a77a431da88ab48638069e658d680dd54c8392 100644
--- a/packages/uni-template-compiler/__tests__/compiler-mp-alipay.spec.js
+++ b/packages/uni-template-compiler/__tests__/compiler-mp-alipay.spec.js
@@ -56,7 +56,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'text',
- 'text',
+ 'text',
undefined,
undefined,
{
diff --git a/packages/uni-template-compiler/lib/constants.js b/packages/uni-template-compiler/lib/constants.js
index 9cd51b9c6d6dfb9370a483c5a8b37acbcd7f6dfd..8d35520f701e2f9fba1146bde2b4539f70bc9d37 100644
--- a/packages/uni-template-compiler/lib/constants.js
+++ b/packages/uni-template-compiler/lib/constants.js
@@ -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: [
diff --git a/packages/uni-template-compiler/lib/script/traverse/data/index.js b/packages/uni-template-compiler/lib/script/traverse/data/index.js
index 16996f7bf6dcf3fe0338f6efea92a00ffe014589..1f78c491f08deec57ec988cf3299347742b4cd83 100644
--- a/packages/uni-template-compiler/lib/script/traverse/data/index.js
+++ b/packages/uni-template-compiler/lib/script/traverse/data/index.js
@@ -1,8 +1,13 @@
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
+ }
}
}
diff --git a/packages/uni-template-compiler/lib/script/traverse/visitor.js b/packages/uni-template-compiler/lib/script/traverse/visitor.js
index 572149fe79aaa0ede9fb549e684285d8246fc97d..bec219549cb607ac8c30b56e308d17465b2dba4b 100644
--- a/packages/uni-template-compiler/lib/script/traverse/visitor.js
+++ b/packages/uni-template-compiler/lib/script/traverse/visitor.js
@@ -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)
}
diff --git a/packages/webpack-uni-mp-loader/lib/plugin/generate-component.js b/packages/webpack-uni-mp-loader/lib/plugin/generate-component.js
index e52a14a7443e66ae287c73f0d10c16962e02d774..73fcbaa03408fdd4c85824609fe14a61807a2efe 100644
--- a/packages/webpack-uni-mp-loader/lib/plugin/generate-component.js
+++ b/packages/webpack-uni-mp-loader/lib/plugin/generate-component.js
@@ -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: ''
+ },
+ {
+ 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) {
diff --git a/packages/webpack-uni-mp-loader/lib/plugin/generate-json.js b/packages/webpack-uni-mp-loader/lib/plugin/generate-json.js
index 493b6f4779bbb4599eab92ab4d987747da09e78b..2fe7b1acd4141dc013051e6101fb31d651c20c06 100644
--- a/packages/webpack-uni-mp-loader/lib/plugin/generate-json.js
+++ b/packages/webpack-uni-mp-loader/lib/plugin/generate-json.js
@@ -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
diff --git a/src/platforms/mp-alipay/runtime/wrapper/component-parser.js b/src/platforms/mp-alipay/runtime/wrapper/component-parser.js
index 3bb329d0179e27ba75a4117119c9862de596a58f..5dc4c94cf2be066c55a47a34e7cbacf02e95d0dc 100644
--- a/src/platforms/mp-alipay/runtime/wrapper/component-parser.js
+++ b/src/platforms/mp-alipay/runtime/wrapper/component-parser.js
@@ -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
-}
+}
diff --git a/src/platforms/mp-alipay/runtime/wrapper/page-parser.js b/src/platforms/mp-alipay/runtime/wrapper/page-parser.js
index 500bdff6e11b50366bc8aa1afaa37d9d3ff39365..756a6534f70efff0de49b47d20ccf4bf3ddbd910 100644
--- a/src/platforms/mp-alipay/runtime/wrapper/page-parser.js
+++ b/src/platforms/mp-alipay/runtime/wrapper/page-parser.js
@@ -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
}
diff --git a/src/platforms/mp-alipay/runtime/wrapper/util.js b/src/platforms/mp-alipay/runtime/wrapper/util.js
index cae35cd61737c3561e866ff90e1f9a0aec8feec9..bfa4757f4005da5b8a32019fade8f993ef503e4a 100644
--- a/src/platforms/mp-alipay/runtime/wrapper/util.js
+++ b/src/platforms/mp-alipay/runtime/wrapper/util.js
@@ -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)
+ }
+ }
+ })
+}