【vue3 原理】注册事件

153 阅读1分钟

准备 demo

App.js

export const App = {
	render(){
		return h(
			'div',
			{
				onClick(){
					console.log('click')
				}
			},
			'Hello, World!'
		)
	}
}

vnode1props添加以on开头的驼峰式函数,必须对应元素的原生事件

具体实现

runtime-core/renderer.js

function mountElement(vnode, container) {
	const el = document.createElement(vnode.type)

	const { children } = vnode
	if (typeof children === 'string') {
		el.textContent = children
	} else if (Array.isArray(children)) {
		 children.forEach(v => {
			 patch(v, el)
		 })
	}

	const { props } = vnode
	for(const key in props){
+		if (key === 'onClick') {
+			el.addEventListener('click', props[key])
+		} else {
			el.setAttribute(key, props[key])
+		}
	}

	container.append(el)
}

事件在初始化元素设置属性中处理

先假设我们只有click事件,只需要判断key为事件则使用addEventListener注册事件,下面改成更通用的实现

通用实现

runtime-core/renderer.js

function mountElement(vnode, container) {
	const el = document.createElement(vnode.type)

	const { children } = vnode
	if (typeof children === 'string') {
		el.textContent = children
	} else if (Array.isArray(children)) {
		 children.forEach(v => {
			 patch(v, el)
		 })
	}

	const { props } = vnode
+	const isOn = (key) => /^on[A-Z]/.test(key)
	for(const key in props){
+		if (isOn(key)) {
+			const event = key.slice(2).toLowerCase()
+			el.addEventListener(event, props[key])
		} else {
			el.setAttribute(key, props[key])
		}
	}

	container.append(el)
}

判断key名是否符合on开头的规则,符合则提取on后面的事件名进行注册

总结

image.png

Footnotes

  1. 创建虚拟节点