vue3实现注册事件功能
首先我们在app.js的render函数中给我们的元素写上onClick事件,如图:
接着我们先实现一下,onClick事件的触发,可以在app.js中看到,我们的时间其实也是在props中的,所以我们可以在render.ts中处理props的位置通过判断key为onClick的时候,为这个元素绑定一个onClick事件,然后把val取出来后去执行
然后我们知道我们会有很多的各种各样的事件,我们不可能一个个进行key的判断然后去做事件的绑定操作;所以我们就思考从具体的click到通用的各种各样的事件绑定。经过我们观察,onClick onMousedown onMouseup...这类事件都是由on + Event name这样的结果构造出来的,所以我们可以通过正则表达式判断是否符合事件,然后给他绑定对应事件,如图
最后我们可以再app.js的render函数中给我们的元素再写上一个onMousedown事件,判断它的通用性是否可以
最终测试结果是正常的:
代码
app.js
import {h} from '../../lib/guide-ljp-vue.esm.js'
window.self = null
export const App = {
// .vue
// <template></template> 最总转化成render函数
// render 由于还没有实现编译功能 所以先直接写render函数
render() {
window.self = this
// ui
return h('div',
{
id:'root',
class:['red','hard'],
onClick(){
console.log('click');
},
onMousedown(){
console.log('mousedown');
}
},
// 在render中通过this访问到setup函数中返回出来的对象的值
'hi, '+this.msg,
// [h('p',{class:'red'},'hi'),h('p',{class:'blue'},'mini-vue')]
)
},
setup(){
return{
msg:'mini-vueljp'
}
}
}
render.ts中主要修改了mountElement函数中的props操作模块
function mountElement(vnode,container){
// 保存根节点到vnode上
const el = ( vnode.el = document.createElement(vnode.type))
const {children,props,shapeFlag} = vnode
// children
if(shapeFlag & shapeFlags.TEXT_CHILDREN) {
el.textContent = children
} else if(shapeFlag & shapeFlags.ARRAY_CHILDREN) {
mountChildren(children,el)
}
// props
for(const key in props){
const val = props[key]
// 具体的click -> 通用
// on + Event name
const isOn = (key:string) => /^on[A-Z]/.test(key)
if(isOn(key)){
el.addEventListener(key.slice(2).toLowerCase(),val)
} else {
el.setAttribute(key,val)
}
}
container.append(el)
}