在React的开发中,咱们常常须要在 window 上注册一些事件, 好比按下 Esc 关闭弹窗, 按上下键选中列表内容等等。比较常见的操做是在组件 mount 的时候去 window 上监听一个事件, 在组件 unmount 的时候中止监听事件。下面给你们介绍几个骚操做。react
咱们建立一个 WindowEventHandler 组件, 内容以下函数
import PropTypes from 'prop-types'; import { Component, PureComponent } from 'react'; export default class WindowEventHandler extends (PureComponent || Component) { static propTypes = { eventName: PropTypes.string.isRequired, callback: PropTypes.func.isRequired, useCapture: PropTypes.bool, }; static defaultProps = { useCapture: false, }; componentDidMount() { const { eventName, callback, useCapture } = this.props; window.addEventListener(eventName, callback, useCapture); } componentWillUnmount() { const { eventName, callback, useCapture } = this.props; window.removeEventListener(eventName, callback, useCapture); } render() { return null; } }
如今好比咱们想在组件A中监听 window 的 resize 事件,咱们在 A 组件中能够这么写ui
export default class A extends (PureComponent || Component) { handleResize = () => { // dosomething... } render() { return ( <div> 我是组件A <WindowEventHandler eventName="resize" callback={this.handleResize} /> </div> ); } }
这样咱们在多个组件中就不须要每次都要写 mount 和 unmount 的钩子函数了,省了不少事情。this
咱们能够给组件写一个统一的装饰器,和以前同样传入事件名和方法名就能够监听,等到组件卸载的时候就中止监听,代码以下code
export default function windowEventDecorator(eventName, fn) { return function decorator(Component) { return (...args) => { const inst = new Component(...args); const instComponentDidMount = inst.componentDidMount ? inst.componentDidMount.bind(inst) : undefined; const instComponentWillUnmount = inst.instComponentWillUnmount ? inst.componentWillUnmount.bind(inst) : undefined; const callback = (e) => { typeof inst[fn] === 'function' && inst[fn](); }; inst.componentDidMount = () => { instComponentDidMount && instComponentDidMount(); document.body.addEventListener(eventName, callback, true); }; inst.componentWillUnmount = () => { instComponentWillUnmount && instComponentWillUnmount(); document.body.removeEventListener(eventName, callback, true); }; return inst; }; }; }
相似这样的装饰器,同理咱们想在 A 中监听 window 的 resize 事件,能够这么写component
@windowEventDecorator('resize', 'handleResize'); export default class A extends (PureComponent || Component) { handleResize = () => { // dosomething... } render() { return ( <div> 我是组件A </div> ); } }
这种小技巧提升了开发效率,少写了不少代码,能够在项目代码中尝试。事件