当前位置: 首页 > 科技观察

面试官:谈谈你对React事件机制的理解?

时间:2023-03-21 16:03:50 科技观察

本文转载自微信公众号《JS日报》,作者慧慧。转载本文请联系JS每日一问公众号。1.什么是反应?它基于浏览器的事件机制,实现了一套事件机制,包括事件注册、事件合成、事件冒泡、事件派发等。React中的这套事件机制称为合成事件合成事件(SyntheticEvent)合成事件是一个event对象,React模拟原生DOM事件的所有能力,即浏览器原生事件的跨浏览器包装器,根据W3C规范定义合成事件,兼容所有浏览器,与浏览器原生事件具有相同的接口,例如:constbutton=button如果想获取原生DOM事件,可以获取constandleClick=(e)=>console.log(e.nativeEvent);通过e.nativeEvent属性;;constbutton=Button从上面我们可以看出React事件和Native事件也很相似,但是也有一定的区别:事件名称命名方式不同//Native事件绑定方法按钮命名//React合成事件绑定方法constbutton=按钮命名事件处理函数写法不同//Native事件事件处理函数写法按钮命名//React合成事件事件处理函数写法constbutton=按钮命名虽然onclick好像是绑定的对于DOM元素,其实并没有事件代理功能,不会直接绑定到真正的节点上,而是所有的事件都会绑定到结构体的最外层,并使用一个统一的事件来监听事件监听器。在事件监听器上维护一个映射,保存所有组件内部的事件监听和处理功能。当组件挂载或卸载时,它只是在这个统一的事件监听器上插入或删除一些对象。当一个事件发生时,首先被这个统一的事件监听器处理,然后在映射中找到真正的事件处理函数并调用它。这样简化了事件处理和回收机制,效率也大大提高。2.执行顺序关于React合成事件和原生事件的执行顺序,可以看下面的例子:);this.childRef=React.createRef();}componentDidMount(){console.log("ReactcomponentDidMount!");this.parentRef.current?.addEventListener("点击",()=>{console.log("原生事件:父元素DOM事件监听!”);});this.childRef.current?.addEventListener("click",()=>{console.log("原生事件:子元素DOM事件监听!");});document.addEventListener("click",(e)=>{console.log("Nativeevent:documentDOMeventlistener!");});}parentClickFun=()=>{console.log("Reactevent:父元素事件监听!");};childClickFun=()=>{console.log("Reactevent:子元素事件监听!");};render(){return(分析事件执行顺序

);}}exportdefaultApp;输出顺序为:原生事件:子元素DOM事件监听器!本机事件:父元素DOM事件监听!React事件:子元素事件监听!React事件:父元素事件监听器!本机事件:documentDOM事件监听器!可以得出以下结论:所有的React事件都挂载在document对象上。当真正的DOM元素触发事件时,它会冒泡到document对象,然后处理React事件。所以会先执行native事件,再处理React事件,最后执行document。挂载事件对应的流程如图所示:因此,如果要防止不同时间段的冒泡行为,需要使用不同的方法,对应如下:防止合成事件之间的冒泡,使用e.stopPropagation()来防止合成事件和最外层文档上事件之间的冒泡,使用e.nativeEvent.stopImmediatePropagation()来防止最外层文档上合成事件和原生事件之间的冒泡,避免document.body.addEventListener('click',e=>{if(e.target&&e.target.matches('div.code')){return;}this.setState({active:false,});});}三、React事件总结机制总结如下:在React上注册的事件最终会绑定到文档的DOM上,而不是React组件对应的DOM(减少内存开销是因为所有事件都绑定到文档上,其他节点没有绑定事件)React实现了一个集合事件冒泡机制本身,所以这就是我们的event.stopPropagation()无效的原因React以队列的形式从触发的组件回溯到父组件,然后调用他们在JSX中定义的回调。React有自己的一套合成事件SyntheticEvent参考https://zh-hans.reactjs.org/docs/events.htmlhttps://segmentfault.com/a/1190000015725214?utm_source=sf-similar-articlehttps://segmentfault.com/a/1190000038251163