vue3的runtime-core-实现注册事件功能

66 阅读1分钟

注册事件的实现方式很简单,重构为通用代码的思路很巧妙

实现事件注册

App.js

这是正常使用结构,实现思路就是从props下手,因为是从props里传过来的

export const App = {
    // 没搞编译,所以template不写,写render就行
    render() {
        // 返回虚拟VNode
        return h('div',
            {
                id: 'root',
                class: ['bgc-red', 'font-blue'],
                // 事件
                onClick() {
                    console.log('click')
                }
            },
            `hi,${this.msg}`
        )
    },
    setup() {
        // composition api
        return {
            msg: 'mini-vue'
        }
    }
}

renderer.ts

找到我们在render里处理props的地方,然后进行进一步处理,我们是在mountElement函数中处理的props

function mountElement(vnode: any, container: any) {
    const { type, props, children, shapeFlag } = vnode
    const el = (vnode.el = document.createElement(type))

    // children
    if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
        el.textContent = children
    }
    else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
        mountChildren(vnode, el)
    }

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

    container.append(el)
}

事件名称都是以on[大写]的格式,所以可以利用正则匹配,测试通过后,进行分割再进行小写转换,就得到了事件名称,回调就是props里的事件注册的函数,所以就是value,直接放进去就行,对正则不熟悉的码友也可以使用映射

这里使用正则匹配要比多分支if判断要来得快,比映射也更简单高效

结语

下一章就是处理组件props逻辑了,祝大家学有所成