第九章 React中的事件处理
我们之前已经了解到在react
中可以通过onXXX
属性来指定处理事件的函数(注意大小写)。
- 且该类型的事件是被
react
处理过,而并非是原生的DOM
事件,这样做的原因是为了兼容性。 react
的事件是通过事件委托的方式处理的,也就是委托给最外层的元素react
的事件有一个event
参数,我们可以通过event.target
拿到发生事件的DOM
元素。
说到这里,我们可以优化一下之前的ref章节的案例:
class Demo extends React.Component {
myRef1 = React.createRef()
myRef2 = React.createRef()
getData = () => {
const val1 = this.myRef1.current.value
console.log(val1)
}
blurData = () => {
const val2 = this.myRef2.current.value
console.log(val2)
}
render () {
return (
<div>
<input ref={this.myRef1} type="text"/>
<button onClick={this.getData}>click</button>
<input ref={this.myRef2} onBlur={this.blurData} type="text"/>
</div>
)
}
}
// 2、将虚拟DOM渲染到页面,标签必须闭合
ReactDOM.render(<Demo />,document.getElementById('app'))
在react
的官方文档里面也说了,不要让我们过度使用ref
,因为它会破坏组件的封装性。使用ref
可以访问组件的DOM
节点,但是这会使组件的实现细节泄漏到其使用者中。这使得组件更难以重构和维护,并且可能导致意外的副作用。另外,过度使用ref
也可能会导致性能问题,因为它可能会使React
无法正确地跟踪组件的状态和属性。因此,React
建议尽可能避免使用ref
,并使用props
和状态来管理组件的行为和状态。
在以上案例中,我们可以看到,在获取第二个输入框的值时,是通过失去焦点事件,该事件就是在输入框元素本身上面。这个时候我们其实就不用ref,通过事件函数触发时拿到事件源就可以获取到值。改造:
class Demo extends React.Component {
myRef1 = React.createRef()
getData = () => {
const val1 = this.myRef1.current.value
console.log(val1)
}
blurData = (event) => {
const val2 = event.target.value
console.log(val2)
}
render () {
return (
<div>
<input ref={this.myRef1} type="text"/>
<button onClick={this.getData}>click</button>
<input onBlur={this.blurData} type="text"/>
</div>
)
}
}
// 2、将虚拟DOM渲染到页面,标签必须闭合
ReactDOM.render(<Demo />,document.getElementById('app'))
以上代码,我们在输入框失去焦点的事件中通过event.target.value
同样拿到了输入框的值。因为该事件发生在元素自身上面。
结语
- 熟练的使用react的事件处理,深度分析组件业务和逻辑构成
- 不要过度使用ref造成性能上的问题
- React的事件系统是跨浏览器的,而原生DOM事件在不同的浏览器中有不同的行为。React的事件系统还提供了更好的性能和更好的事件处理程序封装。
- 此外,React的事件系统还支持事件委托和事件池,这些功能可以提高性能并减少内存使用。