React中的事件
这里的事件:React内置的DOM组件中的事件
- 几乎所有的元素的事件处理,均在document的事件中处理,React会根据虚拟DOM树的完成事件函数的调用
- 一些不冒泡的事件,是直接在元素上监听
- 一些document上面没有的事件,直接在元素上监听
- 如果给真实的DOM注册事件,阻止了事件冒泡,则会导致react的相应事件无法触发(和第三方dom插件混用是需要特别注意)
- 如果给真实的DOM注册事件,事件会先于React事件运行
- React的事件参数,并非真实的DOM事件参数,是React合成的一个对象,该对象类似于真实DOM的事件参数
- e.stopPropagation,通过React的事件中阻止事件冒泡,无法阻止真实的DOM事件冒泡,阻止事件在虚拟DOM树中冒泡(demo1)
- nativeEvent,可以得到真实的DOM事件对象
- 可以通过e.nativeEvent.stopImmediatePropagation(),阻止document上剩余事件的执行
- 为了提高执行效率,React使用事件对象池来处理事件,事件事件中e是同一个
- 在事件处理程序中,不要异步的使用事件对象。如果一定要使用,需要调用persist函数
for (const handler of eventHandlers) {
handler(e);
if (e.isStopped) {
break;
}
}
虚拟dom和真实dom
深入认识setState
setState,它对状态的改变,可能是异步的
如果改变状态的代码处于某个HTML元素的事件中,则其是异步的,否则是同步(比如在定时器中改变state中的值,改变后立刻就可以获取的改变后的值)
如果遇到某个事件中,需要同步调用多次,需要使用函数的方式得到最新状态
最佳实践:
- 把所有的setState当作是异步的
- 永远不要信任setState调用之后的状态
- 如果要使用改变之后的状态,需要使用回调函数(setState的第二个参数)
- 如果新的状态要根据之前的状态进行运算,使用函数的方式改变状态(setState的第一个函数)
React会对异步的setState进行优化,将多次setState进行合并(将多次状态改变完成后,再统一对state进行改变,然后触发render)