事件系统
所有事件都自动绑定到最外层上,若要访问原生事件对象,可以使用 nativeEvent 属性。与原生的浏览器事件一样拥有同样的接口,同样支持事件的冒泡机制,我们可以使用 stopPropagation() 和 preventDefault() 来中断它
在 JSX 中,我们必须使用驼峰的形式来书写事件的属性名(比如onClick ),而 HTML 事件则需要使用全部小写的属性名(比如 onclick )
合成事件的实现机制
- 事件委派
react不会把事件处理函数直接绑定到真实的节点上,而是把所有事件绑定到结构的最外层,使用一个统一的事件监听器。当组件挂载或卸载时,只是在这个统一的事件监听器上插入或删除一些对象;当事件发生时,首先被这个统一的事件监听器处理,然后在映射里找到真正的事件处理函数并调用 - 自动绑定
bind方法。帮助我们绑定事件处理器内的 this ,并可以向事件处理器中传递参数
import React, { Component } from 'react';
class Products extends Component {
handleClick(e, arg) {
console.log(e, arg);
}
render() {
// 通过bind方法实现,可以传递参数
return <button onClick={this.handleClick.bind(this, 'test')}>Test</button>;
}
}
export default Products;
如果方法只绑定,不传参,可选择“双冒号语法”
可改为:<button onClick={::this.handleClick}>Test</button>
构造器内声明。在组件的构造器内完成了 this 的绑定
import React, { Component } from 'react';
class Products extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
console.log(e);
}
render() {
return <button onClick={this.handleClick}>Test</button>;
}
}
export default Products;
箭头函数。自动绑定了定义此函数作用域的 this
可改写为:
import React, { Component } from 'react';
class Products extends Component {
handleClick(e) {
console.log(e);
}
render() {
return <button onClick={() => this.handleClick()}>Test</button>
}
}
export default Products;
或者
import React, { Component } from 'react';
class Products extends Component {
handleClick = (e) => {
console.log(e);
};
render() {
return <button onClick={this.handleClick}>Test</button>;
}
}
export default Products;
在 React 中使用原生事件
import React, { Component } from 'react';
class Products extends Component {
componentDidMount() {
this.refs.button.addEventListener('click', e => {
this.handleClick(e);
});
}
handleClick(e) {
console.log(e);
}
componentWillUnmount() {
this.refs.button.removeEventListener('click');
}
render() {
return <button ref="button">Test</button>;
}
}
export default Products;
在 React 中使用 DOM 原生事件时,一定要在组件卸载时手动移除,否则很可能出现内存泄漏的问题
即在代码行中添加 componentWillUnmount
函数
合成事件与原生事件混用
import React, { Component } from 'react';
class Products extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.handleClickQr = this.handleClickQr.bind(this);
this.state = {
active: false,
};
}
componentDidMount() {
document.body.addEventListener('click', e => {
this.setState({
active: false,
});
});
}
componentWillUnmount() {
document.body.removeEventListener('click');
}
handleClick() {
this.setState({
active: !this.state.active,
});
}
handleClickQr(e) {
e.stopPropagation();
}
render() {
return (
<div className="qr-wrapper">
<button className="qr" onClick={this.handleClick}>图片</button>
<div
className="code"
style={{ display: this.state.active ? 'block' : 'none' }}
onClick={this.handleClickQr}
>
<img src="qr.jpg" alt="qr" />
</div>
</div>
);
}
}
export default Products;
点击“图片”按钮时显示图片,点击空白页面图片隐藏