在弄懂react SyntheticEvent 之前我遇到了一个问题,这个问题一直困扰我很久,知道我看了这篇之后,参考了react 文档,总算弄的大致明白。
首先看一下我的问题。
当我需要在一个点击事件中应用debounce函数(防抖函数)在防止点击事件的多次误触情况是我的第一反应是这样的
options.map(item => { let option = (
这个时候浏览器会报出异常:TypeError: Cannot read property 'getAttribute' of null
检查event对象可以看到target 为null,但是用了debounce 函数之后会出现获取不到event.target的情况呢?接下来需要介绍下react 的合成事件机制。
合成事件(SyntheticEvent)
事件处理程序通过 合成事件(SyntheticEvent)的实例传递,SyntheticEvent 是浏览器原生事件跨浏览器的封装。SyntheticEvent 和浏览器原生事件一样有 stopPropagation()、preventDefault() 接口,而且这些接口夸浏览器兼容。 如果由于某种原因发现您需要基础浏览器事件,只需使用该nativeEvent属性即可获取它。每个SyntheticEvent对象都具有以下属性:
boolean bubblesboolean cancelableDOMEventTarget currentTargetboolean defaultPreventednumber eventPhaseboolean isTrustedDOMEvent nativeEvent // 原生事件对象void preventDefault()boolean isDefaultPrevented()void stopPropagation()boolean isPropagationStopped()DOMEventTarget targetnumber timeStampstring type
事件池
将SyntheticEvent被合并。这意味着SyntheticEvent在调用事件回调之后,将重用该对象并且所有属性都将无效。这是出于性能原因。因此,您无法以异步方式访问事件。
function onClick(event) { console.log(event); // => nullified object. console.log(event.type); // => "click" const eventType = event.type; // => "click" setTimeout(function() { console.log(event.type); // => null console.log(eventType); // => "click" }, 0); // Won't work. this.state.clickEvent will only contain null values. this.setState({clickEvent: event}); // You can still export event properties. this.setState({eventType: event.type});}
注意:如果要以异步方式访问事件属性,则应调用event.persist(),该方法将从池中删除合成事件,并允许用户代码保留对事件的引用。 可以看到react 文档的注意这里给我我们解决办法,因为我们在使用debounce函数时,其内部实际上是使用setTimeout异步调用回调函数,所以直接在debounce函数内部获取外部的event对象是不能直接拿到的,这时调用event.persist()就可以拿到事件的引用。
参考:
在 react 组件中使用 debounce 函数(http://billqiu.github.io/2017/10/15/how-to-debounce-in-react/)
SyntheticEvent(https://reactjs.org/docs/events.html?)