diff --git a/packages/uni-mp-alipay/dist/index.js b/packages/uni-mp-alipay/dist/index.js
index bcb0d824cc489073924099b6a2939df188772b3c..e61a008d2c6e44ddd531440cb57e47c3105cdd7d 100644
--- a/packages/uni-mp-alipay/dist/index.js
+++ b/packages/uni-mp-alipay/dist/index.js
@@ -2478,11 +2478,12 @@ function handleRef (ref) {
if (ref.props['data-com-type'] === 'wx') {
const eventProps = {};
let refProps = ref.props;
+ const eventList = refProps['data-event-list'].split(',');
// 初始化支付宝小程序组件事件
Object.keys(refProps).forEach(key => {
- const handler = refProps[key];
- const res = key.match(/^on([A-Z])(\S*)/);
- if (res && typeof handler === 'function' && handler.name === 'bound handleEvent') {
+ if (eventList.includes(key)) {
+ const handler = refProps[key];
+ const res = key.match(/^on([A-Z])(\S*)/);
const event = res && (res[1].toLowerCase() + res[2]);
refProps[key] = eventProps[key] = function () {
const props = Object.assign({}, refProps);
@@ -2581,7 +2582,23 @@ const handleLink$1 = (function () {
// 支付宝通过 didMount 来实现,先子后父,故等父 ready 之后,统一初始化
(this._$childVues || (this._$childVues = [])).unshift(detail);
}
-})();
+})();
+
+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);
+ };
+ }
+ });
+};
function parseApp (vm) {
Object.defineProperty(Vue.prototype, '$slots', {
@@ -2744,6 +2761,7 @@ function parsePage (vuePageOptions) {
__r: handleRef,
__e: handleEvent,
__l: handleLink$1,
+ __w: handleWrap,
triggerEvent
};
@@ -2860,6 +2878,7 @@ function parseComponent (vueComponentOptions) {
__r: handleRef,
__e: handleEvent,
__l: handleLink$1,
+ __w: handleWrap,
triggerEvent
}
};
@@ -2871,14 +2890,14 @@ function parseComponent (vueComponentOptions) {
componentOptions.deriveDataFromProps = createObserver$1();
} else {
componentOptions.didUpdate = createObserver$1(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/packages/uni-template-compiler/__tests__/compiler-mp-alipay.spec.js b/packages/uni-template-compiler/__tests__/compiler-mp-alipay.spec.js
index f178bf23f0df12d0bd982a18dd64dbcc72ec476b..47a77a431da88ab48638069e658d680dd54c8392 100644
--- a/packages/uni-template-compiler/__tests__/compiler-mp-alipay.spec.js
+++ b/packages/uni-template-compiler/__tests__/compiler-mp-alipay.spec.js
@@ -46,8 +46,8 @@ describe('mp:compiler-mp-alipay', () => {
''
)
assertCodegen(
- 'text',
- 'text',
+ 'text',
+ 'text',
undefined,
undefined,
{
@@ -55,8 +55,8 @@ describe('mp:compiler-mp-alipay', () => {
}
)
assertCodegen(
- 'text',
- 'text',
+ 'text',
+ 'text',
undefined,
undefined,
{
diff --git a/packages/uni-template-compiler/lib/constants.js b/packages/uni-template-compiler/lib/constants.js
index bc38a000a1f3b1dc73d8e219e346754a317cf888..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',
@@ -63,6 +64,7 @@ module.exports = {
ATTR_DATA_EVENT_OPTS: 'data-event-opts',
ATTR_DATA_COM_TYPE: 'data-com-type',
ATTR_DATA_EVENT_PARAMS: 'data-event-params',
+ ATTR_DATA_EVENT_LIST: 'data-event-list',
ATTE_DATA_CUSTOM_HIDDEN: 'data-custom-hidden',
INTERNAL_GET_ORIG,
INTERNAL_GET_CLASS,
@@ -71,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 f1936216860004d9e9cf11849b5e78ccd29e8baa..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,7 +1,13 @@
const t = require('@babel/types')
const {
- ATTR_DATA_COM_TYPE
+ METHOD_CREATE_ELEMENT,
+ ATTR_DATA_EVENT_OPTS,
+ ATTR_DATA_COM_TYPE,
+ ATTR_DATA_EVENT_LIST,
+ ATTR_DATA_EVENT_PARAMS,
+ ATTE_DATA_CUSTOM_HIDDEN,
+ INTERNAL_EVENT_WRAP
} = require('../../../constants')
const processRef = require('./ref')
@@ -37,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),
@@ -51,6 +58,81 @@ module.exports = function traverseData (path, state, tagName) {
t.stringLiteral('__r')
)
)
+ const properties = path.node.properties.find(prop => prop.key.name === 'on').value.properties
+ const list = []
+ for (let index = 0; index < properties.length; index++) {
+ const element = properties[index]
+ if (element.value.value === '__e') {
+ list.push(element.key.value)
+ }
+ }
+ addAttrProperties.push(
+ t.objectProperty(
+ t.stringLiteral(ATTR_DATA_EVENT_LIST),
+ 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 01e9a52f6cd44c3496540f0a6ef091b5c42b30ca..bfa4757f4005da5b8a32019fade8f993ef503e4a 100644
--- a/src/platforms/mp-alipay/runtime/wrapper/util.js
+++ b/src/platforms/mp-alipay/runtime/wrapper/util.js
@@ -115,11 +115,12 @@ export function handleRef (ref) {
if (ref.props['data-com-type'] === 'wx') {
const eventProps = {}
let refProps = ref.props
+ const eventList = refProps['data-event-list'].split(',')
// 初始化支付宝小程序组件事件
Object.keys(refProps).forEach(key => {
- const handler = refProps[key]
- const res = key.match(/^on([A-Z])(\S*)/)
- if (res && typeof handler === 'function' && handler.name === 'bound handleEvent') {
+ if (eventList.includes(key)) {
+ const handler = refProps[key]
+ const res = key.match(/^on([A-Z])(\S*)/)
const event = res && (res[1].toLowerCase() + res[2])
refProps[key] = eventProps[key] = function () {
const props = Object.assign({}, refProps)
@@ -219,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)
+ }
+ }
+ })
+}