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, {
 | 
								utils.processTemplateMacros(rootElement, this, {
 | 
				
			||||||
				updateTextNode: this._updateTextNode.bind(this),
 | 
									updateTextNode: this._updateTextNode.bind(this),
 | 
				
			||||||
				setupAttributeBinding: this._setupAttributeBinding.bind(this),
 | 
									setupAttributeBinding: this._setupAttributeBinding.bind(this),
 | 
				
			||||||
				setupArrowFunctionHandler: this._setupArrowFunctionHandler.bind(this),
 | 
					 | 
				
			||||||
				setupExpressionHandler: this._setupExpressionHandler.bind(this),
 | 
									setupExpressionHandler: this._setupExpressionHandler.bind(this),
 | 
				
			||||||
				setupFunctionCallHandler: this._setupFunctionCallHandler.bind(this),
 | 
									setupFunctionCallHandler: this._setupFunctionCallHandler.bind(this),
 | 
				
			||||||
				stateToElementsMap: this._stateToElementsMap,
 | 
									stateToElementsMap: this._stateToElementsMap,
 | 
				
			||||||
| 
						 | 
					@ -156,6 +155,7 @@ export default (options: ComponentOptions) => {
 | 
				
			||||||
					this._extractStatePathsFromExpression.bind(this),
 | 
										this._extractStatePathsFromExpression.bind(this),
 | 
				
			||||||
				states: this._states,
 | 
									states: this._states,
 | 
				
			||||||
				triggerFunc: this.triggerFunc.bind(this),
 | 
									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
 | 
							// Create handler context
 | 
				
			||||||
		private _createHandlerContext(event: Event, element: Element) {
 | 
							private _createHandlerContext(event: Event, element: Element) {
 | 
				
			||||||
			// Basic context, including state
 | 
								// Basic context, including state
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,11 @@
 | 
				
			||||||
import parseTemplate from './parseTemplate'
 | 
					import parseTemplate from './parseTemplate'
 | 
				
			||||||
import processTemplateMacros from './processTemplateMarco'
 | 
					import processTemplateMacros from './processTemplateMarco'
 | 
				
			||||||
import triggerDomUpdates from './triggerDomUpdates'
 | 
					import triggerDomUpdates from './triggerDomUpdates'
 | 
				
			||||||
 | 
					import setupArrowFunctionHandler from './setupArrowFunctionHandler'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
	parseTemplate,
 | 
						parseTemplate,
 | 
				
			||||||
	processTemplateMacros,
 | 
						processTemplateMacros,
 | 
				
			||||||
	triggerDomUpdates,
 | 
						triggerDomUpdates,
 | 
				
			||||||
 | 
						setupArrowFunctionHandler,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,19 @@ export default function processTemplateMacros(
 | 
				
			||||||
			element: Element,
 | 
								element: Element,
 | 
				
			||||||
			eventName: string,
 | 
								eventName: string,
 | 
				
			||||||
			handlerValue: 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
 | 
							) => void
 | 
				
			||||||
		setupFunctionCallHandler: (
 | 
							setupFunctionCallHandler: (
 | 
				
			||||||
			element: Element,
 | 
								element: Element,
 | 
				
			||||||
| 
						 | 
					@ -153,6 +166,16 @@ export default function processTemplateMacros(
 | 
				
			||||||
						currentElementNode,
 | 
											currentElementNode,
 | 
				
			||||||
						eventName,
 | 
											eventName,
 | 
				
			||||||
						handlerValue,
 | 
											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(')')) {
 | 
									} else if (handlerValue.includes('(') && handlerValue.includes(')')) {
 | 
				
			||||||
					// Handle function call: @click="increment(5)"
 | 
										// 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