提交 f5c34b9c 编写于 作者: Q qiang

Merge branch 'dev' into alpha

......@@ -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
......
......@@ -46,8 +46,8 @@ describe('mp:compiler-mp-alipay', () => {
'<component1 vue-id="{{\'551070e6-1-\'+__i0__}}" ref="__r" data-ref-in-for="{{c4}}" a:for="{{items}}" a:for-item="item" a:for-index="__i0__" onVueInit="__l"></component1>'
)
assertCodegen(
'<component1 @change="onChange">text</component1>',
'<component1 onChange="__e" vue-id="551070e6-1" data-event-opts="{{[[\'^change\',[[\'onChange\']]]]}}" data-com-type="wx" ref="__r" onVueInit="__l">text</component1>',
'<component1 @change="onChange" @cancle="onCancle">text</component1>',
'<component1 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</component1>',
undefined,
undefined,
{
......@@ -55,8 +55,8 @@ describe('mp:compiler-mp-alipay', () => {
}
)
assertCodegen(
'<credit-pay @change="onChange">text</credit-pay>',
'<credit-pay onChange="__e" vue-id="551070e6-1" data-event-opts="{{[[\'^change\',[[\'onChange\']]]]}}" data-com-type="wx" ref="__r" onVueInit="__l">text</credit-pay>',
'<credit-pay @change="onChange" @cancle="onCancle">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',
......@@ -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: [
......
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
}
}
}
......
......@@ -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,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)
}
}
})
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册