Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat mini capture event #1818

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 73 additions & 56 deletions packages/core/src/platform/builtInMixins/proxyEventMixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,70 +4,87 @@ import contextMap from '../../dynamic/vnode/context'

function logCallbackNotFound (context, callbackName) {
const location = context.__mpxProxy && context.__mpxProxy.options.mpxFileResource
error(`Instance property [${callbackName}] is not function, please check.`, location)
error(
`Instance property [${callbackName}] is not function, please check.`,
location
)
}

export default function proxyEventMixin () {
const methods = {
__invoke ($event) {
if (typeof Mpx.config.proxyEventHandler === 'function') {
try {
Mpx.config.proxyEventHandler($event)
} catch (e) {
}
}
const location = this.__mpxProxy.options.mpxFileResource
const type = $event.type
// thanos 平台特殊事件标识
const emitMode = $event.detail && $event.detail.mpxEmit
if (!type) {
error('Event object must have [type] property!', location)
return
}
let fallbackType = ''
if (type === 'begin' || type === 'end') {
// 地图的 regionchange 事件会派发 e.type 为 begin 和 end 的事件
fallbackType = __mpx_mode__ === 'ali' ? 'regionChange' : 'regionchange'
} else if (/-([a-z])/.test(type)) {
fallbackType = dash2hump(type)
} else if (__mpx_mode__ === 'ali') {
fallbackType = type.replace(/^./, i => i.toLowerCase())
}
const target = $event.currentTarget || $event.target
if (!target) {
error(`[${type}] event object must have [currentTarget/target] property!`, location)
return
}
const eventConfigs = target.dataset.eventconfigs || {}
const curEventConfig = eventConfigs[type] || eventConfigs[fallbackType] || []
// 如果有 mpxuid 说明是运行时组件,那么需要设置对应的上下文
const rootRuntimeContext = contextMap.get(target.dataset.mpxuid)
const context = rootRuntimeContext || this
let returnedValue
curEventConfig.forEach((item) => {
const callbackName = item[0]
if (emitMode) {
// thanos 平台特殊事件标识处理
$event = $event.detail.data
}
if (callbackName) {
const params = item.length > 1
? item.slice(1).map(item => {
function handleEvent (context, $event, isCapture) {
if (typeof Mpx.config.proxyEventHandler === 'function') {
try {
Mpx.config.proxyEventHandler($event)
} catch (e) {}
}
const location = context.__mpxProxy.options.mpxFileResource
const type = $event.type
// thanos 平台特殊事件标识
const emitMode = $event.detail && $event.detail.mpxEmit
if (!type) {
error('Event object must have [type] property!', location)
return
}
let fallbackType = ''
if (type === 'begin' || type === 'end') {
// 地图的 regionchange 事件会派发 e.type 为 begin 和 end 的事件
fallbackType = __mpx_mode__ === 'ali' ? 'regionChange' : 'regionchange'
} else if (/-([a-z])/.test(type)) {
fallbackType = dash2hump(type)
} else if (__mpx_mode__ === 'ali') {
fallbackType = type.replace(/^./, (i) => i.toLowerCase())
}
const target = $event.currentTarget || $event.target
if (!target) {
error(
`[${type}] event object must have [currentTarget/target] property!`,
location
)
return
}
const mode = isCapture ? 'capture' : 'bubble'
const eventConfigs = target.dataset.eventconfigs?.[mode] || {}
const curEventConfig = eventConfigs[type] || eventConfigs[fallbackType] || []
// 如果有 mpxuid 说明是运行时组件,那么需要设置对应的上下文
const rootRuntimeContext = contextMap.get(target.dataset.mpxuid)
const runtimeContext = rootRuntimeContext || context
let returnedValue
curEventConfig.forEach((item) => {
const callbackName = item[0]
if (emitMode) {
// thanos 平台特殊事件标识处理
$event = $event.detail.data
}
if (callbackName) {
const params =
item.length > 1
? item.slice(1).map((item) => {
if (item === '__mpx_event__') {
return $event
} else {
return item
}
})
: [$event]
if (typeof context[callbackName] === 'function') {
returnedValue = context[callbackName].apply(context, params)
} else {
logCallbackNotFound(context, callbackName)
}
}
})
return returnedValue
: [$event]
if (typeof runtimeContext[callbackName] === 'function') {
returnedValue = runtimeContext[callbackName].apply(
runtimeContext,
params
)
} else {
logCallbackNotFound(runtimeContext, callbackName)
}
}
})
return returnedValue
}

export default function proxyEventMixin () {
const methods = {
__invoke ($event) {
return handleEvent(this, $event, false)
},
__captureInvoke ($event) {
return handleEvent(this, $event, true)
},
__model (expr, $event, valuePath = ['value'], filterMethod) {
const innerFilter = {
Expand Down
17 changes: 13 additions & 4 deletions packages/webpack-plugin/lib/platform/template/wx/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,16 @@ module.exports = function getSpec ({ warn, error }) {
const modifierStr = match[3] || ''
const rPrefix = runRules(spec.event.prefix, prefix, { mode: 'ali' })
const rEventName = runRules(eventRules, eventName, { mode: 'ali' })
return {
name: dash2hump(rPrefix + '-' + rEventName) + modifierStr,
value
if (rPrefix === 'capture-on' || rPrefix === 'capture-catch') {
return {
name: rPrefix + rEventName.replace(/^[a-z]/, l => l.toUpperCase()) + modifierStr,
value
}
} else {
return {
name: dash2hump(rPrefix + '-' + rEventName) + modifierStr,
value
}
}
},
swan ({ name, value }, { eventRules }) {
Expand Down Expand Up @@ -444,7 +451,9 @@ module.exports = function getSpec ({ warn, error }) {
ali (prefix) {
const prefixMap = {
bind: 'on',
catch: 'catch'
catch: 'catch',
'capture-catch': 'capture-catch',
'capture-bind': 'capture-on'
}
if (!prefixMap[prefix]) {
error(`Ali environment does not support [${prefix}] event handling!`)
Expand Down
84 changes: 57 additions & 27 deletions packages/webpack-plugin/lib/template-compiler/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -1311,6 +1311,32 @@ function processEventReact (el) {
// }
}

function isNeedBind (configs, isProxy) {
if (isProxy) return true
if (configs.length > 1) return true
if (configs.length === 1) return configs[0].hasArgs
return false
}

function processEventBinding (el, configs) {
let resultName
configs.forEach(({ name }) => {
if (name) {
// 清空原始事件绑定
let has
do {
has = getAndRemoveAttr(el, name).has
} while (has)

if (!resultName) {
// 清除修饰符
resultName = name.replace(/\..*/, '')
}
}
})
return { resultName }
}

function processEvent (el, options) {
const eventConfigMap = {}
el.attrsList.forEach(function ({ name, value }) {
Expand All @@ -1324,12 +1350,15 @@ function processEvent (el, options) {
const extraStr = runtimeCompile && prefix === 'catch' ? `, "__mpx_${prefix}"` : ''
const parsedFunc = parseFuncStr(value, extraStr)
if (parsedFunc) {
const isCapture = /^capture/.test(prefix)
if (!eventConfigMap[type]) {
eventConfigMap[type] = {
configs: []
configs: [],
captureConfigs: []
}
}
eventConfigMap[type].configs.push(Object.assign({ name }, parsedFunc))
const targetConfigs = isCapture ? eventConfigMap[type].captureConfigs : eventConfigMap[type].configs
targetConfigs.push(Object.assign({ name }, parsedFunc))
if (modifiers.indexOf('proxy') > -1 || options.forceProxyEvent) {
eventConfigMap[type].proxy = true
}
Expand Down Expand Up @@ -1371,48 +1400,49 @@ function processEvent (el, options) {
}

for (const type in eventConfigMap) {
let needBind = false
const { configs, proxy } = eventConfigMap[type]
const { configs = [], captureConfigs = [], proxy } = eventConfigMap[type]
delete eventConfigMap[type]
if (proxy) {
needBind = true
} else if (configs.length > 1) {
needBind = true
} else if (configs.length === 1) {
needBind = !!configs[0].hasArgs
}

let needBubblingBind = isNeedBind(configs, proxy)
let needCaptureBind = isNeedBind(captureConfigs, proxy)

const escapedType = dash2hump(type)
// 排除特殊情况
if (!isValidIdentifierStr(escapedType)) {
warn$1(`EventName ${type} which need be framework proxy processed must be a valid identifier!`)
needBind = false
needBubblingBind = false
needCaptureBind = false
}

if (needBind) {
let resultName
configs.forEach(({ name }) => {
if (name) {
// 清空原始事件绑定
let has
do {
has = getAndRemoveAttr(el, name).has
} while (has)
if (needBubblingBind) {
const { resultName } = processEventBinding(el, configs)

if (!resultName) {
// 清除修饰符
resultName = name.replace(/\..*/, '')
}
addAttrs(el, [
{
name: resultName || config[mode].event.getEvent(type),
value: '__invoke'
}
])
if (!eventConfigMap.bubble) {
eventConfigMap.bubble = {}
}
eventConfigMap.bubble[escapedType] = configs.map((item) => {
return item.expStr
})
}

if (needCaptureBind) {
const { resultName } = processEventBinding(el, captureConfigs)
addAttrs(el, [
{
name: resultName || config[mode].event.getEvent(type),
value: '__invoke'
value: '__captureInvoke'
}
])
eventConfigMap[escapedType] = configs.map((item) => {
if (!eventConfigMap.capture) {
eventConfigMap.capture = {}
}
eventConfigMap.capture[escapedType] = captureConfigs.map((item) => {
return item.expStr
})
}
Expand Down
Loading