反应合成事件
我想要一个新的开始😇
React
一个用于构建生动闪亮的用户界面的 JavaScript 库🥰。
事件
用户与应用程序交互的不同方式,例如点击、鼠标悬停、输入……等
合成
它是一个...🤔让我们首先了解 React 如何处理事件。
React 在文档级别监听每一个事件,在从浏览器接收到事件后,React 会用一个与原生浏览器事件具有相同接口的包装器来包装这个事件,这意味着我们仍然可以使用像这样的方法preventDefault()
。
那么为什么需要这个包装呢?!😏
想象一下这样的情况:同一个事件在不同的浏览器中有不同的名称。
想象一下当用户眨眼时触发的事件😉,这个事件在 chrome 中称为A,在 Safari 中称为B,在这种情况下,我们需要为每个浏览器做出不同的实现😵。
这个包装器所做的就是为同一个事件效果注册所有不同的名称,在我们的例子中是眨眼,只有一个名称,所以当我们想要监听眨眼效果而不是监听chrome 的A和Safari 的B时,我们只需使用onWink,这是 React 围绕真实事件创建的包装器。
因此,每当我们在 React 组件中触发事件时,我们实际上并不是在处理真正的 DOM 事件,而是在处理 React 的自定义事件类型,即合成事件。
现在闭上你的眼睛😴,但不是这种闭法😅,在你的记忆中回忆起你曾经在 React 组件中使用过的所有 onClick(s)、onBlur(s)、onChange(s),这些都不是真正的事件,这些是 React 的合成事件😇。
因此我们不必再考虑不同浏览器的实现,React 使得创建跨浏览器应用程序变得不再那么痛苦,这意味着我们可以更加专注于将浏览器前缀添加到我们的 CSS 属性😅。
事情还没完,这还不是 React 合成事件的唯一亮点😃。合成事件的另一个引人注目的好处是,React 可以通过池化来重用这些事件对象,从而提升性能。
一旦调用事件处理程序,事件处理程序就是在触发事件后执行的方法,此事件对象上的所有属性将变为无效,设置为空/默认状态,以备再次重用。
到目前为止,一切看起来都很棒,您可能会感觉🧐,但一旦您看到警告:出于浏览器性能原因,此合成事件被重复使用,您可能还会经历一些🤨、🙄甚至😤的时刻。
让我们大多数人经历🤨、🙄和😤时刻的原因不是尽管有红色警告,但实际上是访问事件处理函数中的任何事件属性都失败了
想象一下:
import React, { useState } from "react"
const ExampleComponent = (() => {
const [counter, setCounter] = useState()
function handelArrowBtn(event) {
if (event.keyCode === 40) { //down arrow button
setCounter(counter - 1)
} else if (event.keyCode === 38) { // up arrow button
setCounter(counter + 1)
}
}
return (
<div>
<input
type="number"
value={counter}
onKeyDown={handelArrowBtn}
/>
</div>
)
})
export default ExampleComponent
这个计数器既不会增加也不会减少。我们可爱的红色警告将会打印在浏览器控制台中。
让我们看看这里发生了什么……
handelArrowBtn()
在我们的例子中,在事件处理函数被调用之后,我们的合成事件的对象(onKeyDown
在我们的例子中)被无效,该对象内的键的旧值不再存在,事件对象返回到其原始状态以准备被重用,并且因为这是一个对象,所以我们handelArrowBtn()
可以通过引用访问它,这意味着我们的函数现在可以访问具有其原始状态(无效版本)的事件对象。
那么,我们该如何解决这个问题呢?😯
其实,这个问题可以通过多种方式解决:
- 存储我们需要的事件属性
function handelArrowBtn(event) {
let keyCode = event.keyCode
if (keyCode === 40) {
setCounter(counter - 1)
} else if (keyCode === 38) {
setCounter(counter + 1)
}
}
或者我们也可以将所需的属性作为参数传递给事件处理函数,而不是直接从函数访问它
return (
<div>
<input
type="number"
value={counter}
onKeyDown={(e) => handelArrowBtn(e.keyCode)}
/>
</div>
)
- 使用
event.persist()
它将从池中删除合成事件,这使我们能够在代码中访问事件对象属性
function handelArrowBtn(event) {
event.persist()
if (event.keyCode === 40) {
setCount(count - 1)
} else if (event.keyCode === 38) {
setCount(count + 1)
}
}
希望以上内容对您有所帮助,感谢您的阅读。如果您有任何问题或想让我写一些主题,我很乐意为您提供帮助❤️。
文章来源:https://dev.to/smileycode/react-synthetic-events-34e5