第二十三章 vue3实现注册事件功能

139 阅读2分钟

vue3实现注册事件功能

首先我们在app.js的render函数中给我们的元素写上onClick事件,如图:

image.png

接着我们先实现一下,onClick事件的触发,可以在app.js中看到,我们的时间其实也是在props中的,所以我们可以在render.ts中处理props的位置通过判断key为onClick的时候,为这个元素绑定一个onClick事件,然后把val取出来后去执行

image.png

然后我们知道我们会有很多的各种各样的事件,我们不可能一个个进行key的判断然后去做事件的绑定操作;所以我们就思考从具体的click到通用的各种各样的事件绑定。经过我们观察,onClick onMousedown onMouseup...这类事件都是由on + Event name这样的结果构造出来的,所以我们可以通过正则表达式判断是否符合事件,然后给他绑定对应事件,如图

image.png

最后我们可以再app.js的render函数中给我们的元素再写上一个onMousedown事件,判断它的通用性是否可以

image.png 最终测试结果是正常的:

image.png

代码

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)
}