在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> ); } }
這種小技巧提升了開發效率,少寫了不少代碼,能夠在項目代碼中嘗試。事件