前言

在React的开发中,我们经常需要在 window 上注册一些事件, 比如按下 Esc 关闭弹窗, 按上下键选中列表内容等等。比较常见的操作是在组件 mount 的时候去 window 上监听一个事件, 在组件 unmount 的时候停止监听事件。下面给大家介绍几个骚操作。

WindowEventHandler

我们创建一个 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 组件中可以这么写


export default class A extends (PureComponent || Component) { handleResize = () => {
// dosomething...
}
render() {
return (
<div>
我是组件A
<WindowEventHandler eventName="resize" callback={this.handleResize} />
</div>
);
}
}

这样我们在多个组件中就不需要每次都要写 mount 和 unmount 的钩子函数了,省了很多事情。

使用装饰器

我们可以给组件写一个统一的装饰器,和之前一样传入事件名和方法名就可以监听,等到组件卸载的时候就停止监听,代码如下


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 事件,可以这么写


@windowEventDecorator('resize', 'handleResize');
export default class A extends (PureComponent || Component) { handleResize = () => {
// dosomething...
}
render() {
return (
<div>
我是组件A
</div>
);
}
}

总结

这种小技巧提高了开发效率,少写了很多代码,可以在项目代码中尝试。

来源:https://segmentfault.com/a/1190000017348517

优雅的在React组件中注册事件的更多相关文章

  1. 如何优雅的设计React组件

    如何优雅的设计 React 组件 如今的 web 前端已被 React.Vue 和 Angular 三分天下,一统江山十几年的 jQuery 显然已经很难满足现在的开发模式.那么,为什么大家会觉得 j ...

  2. 如何优雅地在React项目中使用Redux

    前言 或许你当前的项目还没有到应用Redux的程度,但提前了解一下也没有坏处,本文不会安利大家使用Redux 概念 首先我们会用到哪些框架和工具呢? React UI框架 Redux 状态管理工具,与 ...

  3. 规避 React 组件中的 bind(this)

    React 组件中处理 onClick 类似事件绑定的时候,是需要显式给处理器绑定上下文(context)的,这一度使代码变得冗余和难看. 请看如下的示例: class App extends Com ...

  4. 优雅的在React项目中使用Redux

    概念 首先我们会用到哪些框架和工具呢? React UI框架 Redux 状态管理工具,与React没有任何关系,其他UI框架也可以使用Redux react-redux React插件,作用:方便在 ...

  5. 【React】282- 在 React 组件中使用 Refs 指南

    英文:Yomi Eluwande  译文:joking_zhang https://segmentfault.com/a/1190000019277029 使用 React 时,我们的默认思维方式应该 ...

  6. React组件中对子组件children进行加强

    React组件中对子组件children进行加强 问题 如何对组件的children进行加强,如:添加属性.绑定事件,而不是使用<div>{this.props.children}< ...

  7. 在 React 组件中使用 Refs 指南

    原文:Fullstack React's Guide to using Refs in React Components作者:Yomi Eluwande译者:博轩 译文:https://segment ...

  8. react组件中的constructor和super小知识

    react组件中的constructor和super小知识 1.react中用class申明的类一些小知识 如上图:类Child是通过class关键字申明,并且继承于类React. A.Child的类 ...

  9. React组件中的key

    React组件中的key 一.key的作用 react中的key属性,它是一个特殊的属性,它是出现不是给开发者用的(例如你为一个组件设置key之后不能获取组件的这个key props),而是给reac ...

随机推荐

  1. 重学c#系列——盛派自定义异常源码分析(八)

    前言 接着异常七后,因为以前看过盛派这块代码,正好重新整理一下. 正文 BaseException 首先看下BaseException 类: 继承:public class BaseException ...

  2. [源码解析] Flink的Slot究竟是什么?(1)

    [源码解析] Flink的Slot究竟是什么?(1) 目录 [源码解析] Flink的Slot究竟是什么?(1) 0x00 摘要 0x01 概述 & 问题 1.1 Fllink工作原理 1.2 ...

  3. Flink启动脚本改造--制作适用于CDH的Flink parcel包

    #!/usr/bin/env bash ################################################################################ ...

  4. Linux教学资源服务器构建

    1. 需求分析 1.1 课题简介 随着计算机互联网的迅速发展,大多数学校已经实现教学的信息化,从传统的黑板教学方式转变为现阶段的多媒体教学,教学的资源,素材课件,甚至学生的作业也都实现数字化,为了实现 ...

  5. Qt 关于图片打开,另存为,保存到指定位置操作

    Qt 关于图片打开,另存为,保存到指定位置操作(转载) 在头文件mainwindow.h中先声明以下类: 1 #include <QImage> 2 #include <QPixma ...

  6. 手写@Service、@Autowired、@Transactional注解,实现spring ioc和spring事务

    自定义@Service注解 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Custom ...

  7. 23种设计模式 - 行为变化(Command - Visitor)

    其他设计模式 23种设计模式(C++) 每一种都有对应理解的相关代码示例 → Git原码 ⌨ 行为变化 Command 动机(Motivation) 在软件构建过程中,"行为请求者" ...

  8. 0827考试 T1

    Description ​ 有一棵树,每个点有一个权值,找到一个权值最大的"乙烷"模型. ​ "乙烷"模型是指: ​ 其中黑点表示可以有0个或多个点. Samp ...

  9. python笔记-dumps()与loads()的使用

    json.dumps是将一个Python数据类型列表进行json格式的编码解析, 示例如下: >>> import json #导入python 中的json模块 >>& ...

  10. Canalv1.1.4版本搭建HA集群

    前提 Canal上一个正式版是于2019-9-2发布的v1.1.4,笔者几个月前把这个版本的Canal推上了生产环境,部署了HA集群.过程中虽然遇到不少的坑,但是在不出问题的前提下,Canal的作用还 ...