关于 Decorator 到底是 ES 6 引入的还是 ES 7 引入的我也不是很明白了,两种说法都有,这种问题懒得纠结了……在用的时候发现这个东西很好用,平常用处可能不大,但是结合 React 就很好使了。接下来就讲一讲。

一、环境搭建

我搭建了一个 React 开发环境,结合 babel 的插件——babel-plugin-transform-decorators-legacy一起使用,这个插件可以让你写 Decorator。

GitHub 地址:https://github.com/zhongdeming428/HOC

可以通过如下命令克隆:

$ git clone https://github.com/zhongdeming428/HOC.git

克隆下来以后就可以尝试啦!

二、Decorator 的基本使用

装饰器本身就是一个函数,使用起来挺简单,无非就是修饰类或者类的函数。使用 @ 调用,扔在要修饰的类或者类方法前面就可以了。但是在修饰类和类函数的时候又有细微的差异。

class A {
@sayB
sayA() {
console.log('a');
}
}
function sayB(target, name, descriptor) {
// ...
}

在使用装饰器装饰类函数的时候,可以接受三个参数。第一个是要修饰的对象,第二个是修饰的属性名,第三个是属性描述符。可以在我搭建的项目中进行尝试。

在用装饰器装饰类的时候,只能够接受一个参数——target。这区别于上面的情况:

@APlus
class A { }
function APlus(target, name, descriptor) {
// ... 打印一下可以发现 name、descriptor 是 undefined。
}

另外,装饰器还可以接受参数,返回一个符合装饰器规范的新函数即可,这样又可以对装饰器的装饰行为进行定制了。比如:

@attach2Prop({ name: 'A' })
class A { } @attach2Prop({ name: 'B' })
class B { } function attach2Prop(obj) {
return function(target) {
target.prototype.$data = obj;
}
} console.log((new A()).$data.name);
console.log((new B()).$data.name);

结果会输出 AB

这就就可以用同一个装饰器实现不同行为的装饰了。

那么结合 React 有什么妙用呢?

三、结合 React 使用

(1)简化 React-Redux 的使用

以往在使用 react-redux 时,在定义好 UI 组件后,还要定义容器组件:

class UIComponent extends React.Component {

}

const ContainerComponent = connect(mapState2Props, mapDispatch2Props)(UIComponent);

export default ContainerComponent;

有了装饰器之后:

@connect(mapState2Props, mapDispatch2Props)
class UIComponent extends React.Component { } export default UIComponent;

这样用简化的代码达到了同样的效果,还省去了给容器组件命名的麻烦……代码也更加的整洁。

(2)定制高阶组件

上一小节中的容器组件实际上就是一个高阶组件,但是我们自己有时候也要定义一些高阶组件,实现代码的更高层次的复用。

例如:我们做了一个组件库,里面有一部分的组件是有一个功能特征的,那就是可以拖拽;又比如我们做的移动端组件,需要实现一个左滑删除功能。我们需要给每种具有这个特征的组件写一遍拖拽或者左滑删除逻辑吗?

显然是否定的,我们可以实现一个纯逻辑组件,而非 UI 组件,它的功能就是使得你的 UI 组件具有某种特定功能。比如上面提到的左滑删除或者拖拽。

这个纯逻辑组件就可以是一个装饰器,是一个高阶组件。

在我搭建的开发环境中,就实现了这样一个简单的高阶组件,让你的 UI 组件在鼠标滑入时显示为一只手。

装饰器代码如下:

// src/decorators/CursorPointer.js
import React from 'react'; export default Component => class extends React.Component {
render() {
return <div style={{cursor: 'pointer', display: 'inline-block'}}>
<Component/>
</div>
}
}

这个装饰器(高阶组件)接受一个 React 组件作为参数,然后返回一个新的 React 组件。实现很简单,就是包裹了一层 div,添加了一个 style,就这么简单。以后所有被它装饰的组件都会具有这个特征。

使用这个装饰器:

import React from 'react';
import Clickable from '../decorators/CursorPointer'; @Clickable
class ClickablePanel extends React.Component {
render() {
return <div className="panel"> </div>
}
} export default ClickablePanel;

将装饰器与高阶组件相结合,可以大大优化你的 React 代码!

ES 6 装饰器与 React 高阶组件的更多相关文章

  1. 函数式编程与React高阶组件

    相信不少看过一些框架或者是类库的人都有印象,一个函数叫什么creator或者是什么什么createToFuntion,总是接收一个函数,来返回另一个函数.这是一个高阶函数,它可以接收函数可以当参数,也 ...

  2. React高阶组件学习笔记

    高阶函数的基本概念: 函数可以作为参数被传递,函数可以作为函数值输出. 高阶组件基本概念: 高阶组件就说接受一个组件作为参数,并返回一个新组件的函数. 为什么需要高阶组件 多个组件都需要某个相同的功能 ...

  3. react高阶组件的理解

    [高阶组件和函数式编程] function hello() { console.log('hello jason'); } function WrapperHello(fn) { return fun ...

  4. react高阶组件的一些运用

    今天学习了react高阶组件,刚接触react学习起来还是比较困难,和大家分享一下今天学习的知识吧,另外缺少的地方欢迎补充哈哈 高阶组件(Higher Order Components,简称:HOC) ...

  5. 聊聊React高阶组件(Higher-Order Components)

    使用 react已经有不短的时间了,最近看到关于 react高阶组件的一篇文章,看了之后顿时眼前一亮,对于我这种还在新手村晃荡.一切朝着打怪升级看齐的小喽啰来说,像这种难度不是太高同时门槛也不是那么低 ...

  6. 当初要是看了这篇,React高阶组件早会了

    当初要是看了这篇,React高阶组件早会了. 概况: 什么是高阶组件? 高阶部件是一种用于复用组件逻辑的高级技术,它并不是 React API的一部分,而是从React 演化而来的一种模式. 具体地说 ...

  7. 利用 React 高阶组件实现一个面包屑导航

    什么是 React 高阶组件 React 高阶组件就是以高阶函数的方式包裹需要修饰的 React 组件,并返回处理完成后的 React 组件.React 高阶组件在 React 生态中使用的非常频繁, ...

  8. react高阶组件的使用

    为了提高代码的复用在react中我们可以使用高阶组件 1.添加高阶组件 高阶组件主要代码模板HOC.js export default (WrappedComponent) => { retur ...

  9. react高阶组件

    高阶组件 为了提高组件复用性,在react中就有了HOC(Higher-Order Component)的概念.所谓的高阶组件,其本质依旧是组件,只是它返回另外一个组件,产生新的组件可以对属性进行包装 ...

随机推荐

  1. shell 10个好习惯

    The Linux Cookbook 一书的作者 Michael Stutz 凭借自己多年使用 UNIX 的经验,总结了 10 个良好习惯,个人认为真的很受用,现摘要如下与大家分享. 1.建立层级目录 ...

  2. TCP/IP提供网络传输速率

    丢包(超时)->减少超时时间->ECN(有网络设备通知终端,有丢包发生)->DCTCP(优化快恢复) 丢包是超时的充分条件,但不是必要条件,因此也可通过其他方式获得丢包是否发生,比如 ...

  3. this说明

    这个This就表示当前实例的对象,用this可访问属性,this.Fist:

  4. [javaSE] 网络编程(浏览器客户端-自定义服务端)

    获取ServerSocket对象,new出来构造参数:int类型端口号 调用ServerSocket对象的accept()方法,得到Socket对象 获取PrintWriter对象,new出来,构造参 ...

  5. HDU 2639(01背包第K大)

    http://acm.hdu.edu.cn/showproblem.php?pid=2639 http://blog.csdn.net/lulipeng_cpp/article/details/758 ...

  6. ThreeJs 选中物体事件

    选中物体变红色demo: https://threejs.org/examples/#webgl_raycast_sprite <!DOCTYPE html> <html lang= ...

  7. 验证两台机器已经建立的ssh互信

    1.expect方法 #!/bin/bash checkTrust() { expect -c ' set timeout 2; spawn ssh $1 "expr 12345678 + ...

  8. BottomNavigationView结合ViewPager

    BottomNavigationView是Google推出的底部导航栏组件,在没有这些底部导航组件之前,Android开发者多使用的是RadioGroup,在上一个项目开发中我们使用了Google的B ...

  9. IEC62304软件维护框架

    软件维护计划的任务 建立接收.记录.评估.解决和追踪医疗器械软件发行后的反馈 制定确认反馈是否是问题的标准 使用风险管理过程 使用配置管理过程 制定升级.补丁以及遗留问题修正计划 问题和修改分析的任务 ...

  10. 星空灯改装成USB供电

    简单的手工活,20分钟搞定 1.用一根USB线剪断,将红黑两根线分别连接到星空灯电源供电的正负极 2.由于USB输出5V 0.5A的电流,因此需要改装下,办法一,加电阻,办法二,换灯泡,由于小电阻并不 ...