我们之前已经了解到在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的事件系统还支持事件委托和事件池,这些功能可以提高性能并减少内存使用。