refactor: move arrow function handler logic to a dedicated utility function
This commit is contained in:
parent
8f6b4a6cd9
commit
fe046f4500
67
src/main.ts
67
src/main.ts
|
@ -137,7 +137,6 @@ export default (options: ComponentOptions) => {
|
|||
utils.processTemplateMacros(rootElement, this, {
|
||||
updateTextNode: this._updateTextNode.bind(this),
|
||||
setupAttributeBinding: this._setupAttributeBinding.bind(this),
|
||||
setupArrowFunctionHandler: this._setupArrowFunctionHandler.bind(this),
|
||||
setupExpressionHandler: this._setupExpressionHandler.bind(this),
|
||||
setupFunctionCallHandler: this._setupFunctionCallHandler.bind(this),
|
||||
stateToElementsMap: this._stateToElementsMap,
|
||||
|
@ -156,6 +155,7 @@ export default (options: ComponentOptions) => {
|
|||
this._extractStatePathsFromExpression.bind(this),
|
||||
states: this._states,
|
||||
triggerFunc: this.triggerFunc.bind(this),
|
||||
setupArrowFunctionHandler: utils.setupArrowFunctionHandler.bind(this),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -243,71 +243,6 @@ export default (options: ComponentOptions) => {
|
|||
)
|
||||
}
|
||||
|
||||
// Handle arrow function
|
||||
private _setupArrowFunctionHandler(
|
||||
element: Element,
|
||||
eventName: string,
|
||||
handlerValue: string,
|
||||
) {
|
||||
element.addEventListener(eventName, (event: Event) => {
|
||||
try {
|
||||
// Arrow function parsing
|
||||
const splitted = handlerValue.split('=>')
|
||||
if (splitted.length !== 2) {
|
||||
throw new Error(`Invalid arrow function syntax: ${handlerValue}`)
|
||||
}
|
||||
const paramsStr = (() => {
|
||||
if (splitted[0].includes('(')) return splitted[0].trim()
|
||||
return `(${splitted[0].trim()})`
|
||||
})()
|
||||
const bodyStr = splitted[1].trim()
|
||||
|
||||
// Check if the function body is wrapped in {}
|
||||
const isMultiline = bodyStr.startsWith('{') && bodyStr.endsWith('}')
|
||||
|
||||
// If it is a multiline function body, remove the outer braces
|
||||
if (isMultiline) {
|
||||
// Remove the outer braces
|
||||
let bodyStr = handlerValue.split('=>')[1].trim()
|
||||
bodyStr = bodyStr.substring(1, bodyStr.length - 1)
|
||||
|
||||
// Build code for multiline arrow function
|
||||
const functionCode = `
|
||||
return function${paramsStr} {
|
||||
${bodyStr}
|
||||
}
|
||||
`
|
||||
|
||||
// Create context object
|
||||
const context = this._createHandlerContext(event, element)
|
||||
|
||||
// Create and call function
|
||||
const handlerFn = new Function(functionCode).call(null)
|
||||
handlerFn.apply(context, [event])
|
||||
} else {
|
||||
// Single line arrow function, directly return expression result
|
||||
const functionCode = `
|
||||
return function${paramsStr} {
|
||||
return ${bodyStr}
|
||||
}
|
||||
`
|
||||
|
||||
// Create context object
|
||||
const context = this._createHandlerContext(event, element)
|
||||
|
||||
// Create and call function
|
||||
const handlerFn = new Function(functionCode).call(null)
|
||||
handlerFn.apply(context, [event])
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(
|
||||
`Error executing arrow function handler: ${handlerValue}`,
|
||||
err,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Create handler context
|
||||
private _createHandlerContext(event: Event, element: Element) {
|
||||
// Basic context, including state
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import parseTemplate from './parseTemplate'
|
||||
import processTemplateMacros from './processTemplateMarco'
|
||||
import triggerDomUpdates from './triggerDomUpdates'
|
||||
import setupArrowFunctionHandler from './setupArrowFunctionHandler'
|
||||
|
||||
export default {
|
||||
parseTemplate,
|
||||
processTemplateMacros,
|
||||
triggerDomUpdates,
|
||||
setupArrowFunctionHandler,
|
||||
}
|
||||
|
|
|
@ -13,6 +13,19 @@ export default function processTemplateMacros(
|
|||
element: Element,
|
||||
eventName: string,
|
||||
handlerValue: string,
|
||||
ops: {
|
||||
createHandlerContext: (
|
||||
event: Event,
|
||||
element: Element,
|
||||
) => {
|
||||
states: Record<string, unknown>
|
||||
stateToElementsMap: Record<string, Set<HTMLElement>>
|
||||
statesListeners: Record<string, (value: unknown) => void>
|
||||
setState: (keyPath: string, value: unknown) => void
|
||||
getState: (keyPath: string) => unknown
|
||||
triggerFunc: (eventName: string, ...args: unknown[]) => void
|
||||
}
|
||||
},
|
||||
) => void
|
||||
setupFunctionCallHandler: (
|
||||
element: Element,
|
||||
|
@ -153,6 +166,16 @@ export default function processTemplateMacros(
|
|||
currentElementNode,
|
||||
eventName,
|
||||
handlerValue,
|
||||
{
|
||||
createHandlerContext: (_event: Event, _element: Element) => ({
|
||||
states: options.states,
|
||||
stateToElementsMap: options.stateToElementsMap,
|
||||
statesListeners: options.stateListeners,
|
||||
setState: context.setState.bind(context),
|
||||
getState: context.getState.bind(context),
|
||||
triggerFunc: options.triggerFunc.bind(context),
|
||||
}),
|
||||
},
|
||||
)
|
||||
} else if (handlerValue.includes('(') && handlerValue.includes(')')) {
|
||||
// Handle function call: @click="increment(5)"
|
||||
|
|
76
src/utils/setupArrowFunctionHandler.ts
Normal file
76
src/utils/setupArrowFunctionHandler.ts
Normal file
|
@ -0,0 +1,76 @@
|
|||
export default function setupArrowFunctionHandler(
|
||||
element: Element,
|
||||
eventName: string,
|
||||
handlerValue: string,
|
||||
ops: {
|
||||
createHandlerContext: (
|
||||
event: Event,
|
||||
element: Element,
|
||||
) => {
|
||||
states: Record<string, unknown>
|
||||
stateToElementsMap: Record<string, Set<HTMLElement>>
|
||||
statesListeners: Record<string, (value: unknown) => void>
|
||||
setState: (keyPath: string, value: unknown) => void
|
||||
getState: (keyPath: string) => unknown
|
||||
triggerFunc: (eventName: string, ...args: unknown[]) => void
|
||||
}
|
||||
},
|
||||
) {
|
||||
element.addEventListener(eventName, (event: Event) => {
|
||||
try {
|
||||
// Arrow function parsing
|
||||
const splitted = handlerValue.split('=>')
|
||||
if (splitted.length !== 2) {
|
||||
throw new Error(`Invalid arrow function syntax: ${handlerValue}`)
|
||||
}
|
||||
const paramsStr = (() => {
|
||||
if (splitted[0].includes('(')) return splitted[0].trim()
|
||||
return `(${splitted[0].trim()})`
|
||||
})()
|
||||
const bodyStr = splitted[1].trim()
|
||||
|
||||
// Check if the function body is wrapped in {}
|
||||
const isMultiline = bodyStr.startsWith('{') && bodyStr.endsWith('}')
|
||||
|
||||
// If it is a multiline function body, remove the outer braces
|
||||
if (isMultiline) {
|
||||
// Remove the outer braces
|
||||
let bodyStr = handlerValue.split('=>')[1].trim()
|
||||
bodyStr = bodyStr.substring(1, bodyStr.length - 1)
|
||||
|
||||
// Build code for multiline arrow function
|
||||
const functionCode = `
|
||||
return function${paramsStr} {
|
||||
${bodyStr}
|
||||
}
|
||||
`
|
||||
|
||||
// Create context object
|
||||
const context = ops.createHandlerContext(event, element)
|
||||
|
||||
// Create and call function
|
||||
const handlerFn = new Function(functionCode).call(null)
|
||||
handlerFn.apply(context, [event])
|
||||
} else {
|
||||
// Single line arrow function, directly return expression result
|
||||
const functionCode = `
|
||||
return function${paramsStr} {
|
||||
return ${bodyStr}
|
||||
}
|
||||
`
|
||||
|
||||
// Create context object
|
||||
const context = ops.createHandlerContext(event, element)
|
||||
|
||||
// Create and call function
|
||||
const handlerFn = new Function(functionCode).call(null)
|
||||
handlerFn.apply(context, [event])
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(
|
||||
`Error executing arrow function handler: ${handlerValue}`,
|
||||
err,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user