react事件
1.事件机制
大体来说,react的事件机制分为两部分,一个是事件注册,一个是事件分发
- 事件注册部分: 所有的事件都是注册到document上
- 事件分发部分: 所有的事件由同意的回调函数(dispatchEvent)来执行事件分发;首先生成合成事件(Event) ,同一类型的事件(比如onclick事件)会合成一个事件(Event),dom上所有绑定的onclick的回调函数都会按照顺序(事件冒泡或者事件捕获)放到Event._dispatchListeners这个数组里,依次执行里面的函数
2.阻止默认事件
我们都知道,a标签是带有默认跳转事件的(当a标签的href属性为空时,默认是当前页面的地址,所以点击会刷新当前页面),如果我们在a标签上注册一个点击事件,既会触发点击事件,也会触发a标签的跳转事件
使用 e.preventDefault() 阻止默认事件
例如:
function stopDefaultEvent(e){
e.preventDefault()
console.log('stop event');
}
return (
<div className="App">
<a href="" onClick= { stopDefaultEvent }>事件处理</a>
</div>
);
3.尽量不要使用 addEventListener
尽量不要使用原生js注册事件的方式addEventListener
为了提高框架的性能,React 通过 DOM 事件冒泡,只在 document 节点上注册原生的 DOM 事件,React 内部自己管理所有组件的事件处理函数,以及事件的冒泡、捕获。
所以说,如果你通过 addEventListener 注册了某个 DOM 节点的某事件处理函数,并且通过 e.stopPropagation(); 阻断了事件的冒泡或者捕获,那么该节点下的所有节点上,同类型的 React 事件处理函数都会失效。
例如:
class CounterLink extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
}
this.handleClick = this.handleClick.bind(this);
}
componentDidMount() {
document.querySelector('.my-link').addEventListener('click', (e) => {
console.info('raw click');
e.stopPropagation();
})
}
handleClick(e) {
e.preventDefault();
console.info('react click');
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div className="my-link">
<a href="#" onClick={this.handleClick}>Clicked me {this.state.count} times.</a>
</div>
)
}
}
ReactDOM.render(<CounterLink/>, document.querySelector("#root"));
虽然设置的链接的点击事件,但是它却执行不了
4.react注册事件的几种方式
- 1.bind this
当你使用 ES6 class 语法定义一个组件的时候,通常的做法是将事件处理函数声明为 class 中的方法
import React from "react";
export default class Home extends React.Component {
constructor(props) {
super(props);
this.toWeather = this.toWeather.bind(this);
}
toWeather() {
this.props.history.push("/weather");
}
render() {
return (
<div>
<span onClick={this.toWeather}>go weather</span>
</div>
);
}
}
- 2.class fields
如果你正在使用实验性的 public class fields 语法,你可以使用 class fields 正确的绑定回调函数:
import React from "react";
export default class Home extends React.Component {
toWeather = () => {
this.props.history.push("/weather");
};
render() {
return (
<div>
<span onClick={this.toWeather}>go weather</span>
</div>
);
}
}
- 3.箭头函数
import React from "react";
export default class Home extends React.Component {
toWeather() {
this.props.history.push("/weather");
}
render() {
return (
<div>
<span onClick={() => this.toWeather()}>go weather</span>
</div>
);
}
}
- 4.箭头函数带来的性能问题:
箭头函数语法问题在于每次渲染 LoggingButton 时都会创建不同的回调函数。在大多数情况下,这没什么问题,但如果该回调函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。我们通常建议在构造器中绑定或使用 class fields 语法来避免这类性能问题。

浙公网安备 33010602011771号