ES 6 装饰器与 React 高阶组件
关于 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);
结果会输出 A 和 B。
这就就可以用同一个装饰器实现不同行为的装饰了。
那么结合 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 高阶组件的更多相关文章
- 函数式编程与React高阶组件
相信不少看过一些框架或者是类库的人都有印象,一个函数叫什么creator或者是什么什么createToFuntion,总是接收一个函数,来返回另一个函数.这是一个高阶函数,它可以接收函数可以当参数,也 ...
- React高阶组件学习笔记
高阶函数的基本概念: 函数可以作为参数被传递,函数可以作为函数值输出. 高阶组件基本概念: 高阶组件就说接受一个组件作为参数,并返回一个新组件的函数. 为什么需要高阶组件 多个组件都需要某个相同的功能 ...
- react高阶组件的理解
[高阶组件和函数式编程] function hello() { console.log('hello jason'); } function WrapperHello(fn) { return fun ...
- react高阶组件的一些运用
今天学习了react高阶组件,刚接触react学习起来还是比较困难,和大家分享一下今天学习的知识吧,另外缺少的地方欢迎补充哈哈 高阶组件(Higher Order Components,简称:HOC) ...
- 聊聊React高阶组件(Higher-Order Components)
使用 react已经有不短的时间了,最近看到关于 react高阶组件的一篇文章,看了之后顿时眼前一亮,对于我这种还在新手村晃荡.一切朝着打怪升级看齐的小喽啰来说,像这种难度不是太高同时门槛也不是那么低 ...
- 当初要是看了这篇,React高阶组件早会了
当初要是看了这篇,React高阶组件早会了. 概况: 什么是高阶组件? 高阶部件是一种用于复用组件逻辑的高级技术,它并不是 React API的一部分,而是从React 演化而来的一种模式. 具体地说 ...
- 利用 React 高阶组件实现一个面包屑导航
什么是 React 高阶组件 React 高阶组件就是以高阶函数的方式包裹需要修饰的 React 组件,并返回处理完成后的 React 组件.React 高阶组件在 React 生态中使用的非常频繁, ...
- react高阶组件的使用
为了提高代码的复用在react中我们可以使用高阶组件 1.添加高阶组件 高阶组件主要代码模板HOC.js export default (WrappedComponent) => { retur ...
- react高阶组件
高阶组件 为了提高组件复用性,在react中就有了HOC(Higher-Order Component)的概念.所谓的高阶组件,其本质依旧是组件,只是它返回另外一个组件,产生新的组件可以对属性进行包装 ...
随机推荐
- Linux安装AUTOCONF和AUTOMAKE产生的程序的一般步骤
概述: 在Linux下安装一个应用程序时, 一般先运行脚本configure, 然后用make来编译源程序, 在运行make install, 最后运行make clean删除一些临时文件. 相关点的 ...
- Vue学习笔记:methods、computed、watch的区别
自:https://www.jb51.net/article/120073.htm 首先要说,methods,watch和computed都是以函数为基础的,但各自却都不同 而从作用机制和性质上看,m ...
- ASP.NET 表单验证方法与客户端(浏览器)服务器交互机制的故事
想到这个问题完全是一个意外吧,是在寻找另外一个问题答案的过程中,才对验证方法与浏览器服务器交互机制的关系有了清晰的认识. 先说下验证方法,验证方法分为前台验证和后台验证. 前台验证就是类似jQuery ...
- (JSP)关于手机端(尤其是苹果手机)pdf文件无法打开的解决方案
流的方式下载附件 <!-- @author :daisy @date : 2011-12-04 @note : 从数据库中读取BLOB图片显示 --> <%@page import= ...
- python循环删除列表里的元素!漏删!
li = [1,2,3,4,5,6] for i in li: if i<3: li.remove(i) print(li) #输出的结果是 [2,3,4,5,6] 2没有remove掉 ...
- JavaScript函数与面向对象
一.JS面向对象 function Func(name,age){ //this = obj this.Name = name; this.Age = age; } obj = new Func('r ...
- PHP获取本地时间
使用date ( "Y-m-d H:i:s" )函数获取当前时间,总是不对,原来默认是格林威治时间,解决的办法有两个: 1.获取之前先加 date_default_timezo ...
- HTML 5 教程
HTML5 是下一代的 HTML.有必要再过一遍.看下要点. 具体看 http://www.w3school.com.cn/html5/index.asp 教程 和 HTML5 标签参考手册 ...
- 微服务&spring cloud架构系列汇总
为了方便查找,把微服务&微服务架构之spring cloud架构系列文章按时间正序整理了一下,记录如下: 1. 微服务架构之spring cloud 介绍 2. 微服务架构之spring ...
- INNODB与MyISAM两种表存储引擎区别
mysql数据库分类为INNODB为MyISAM两种表存储引擎了,两种各有优化在不同类型网站可能选择不同,下面小编为各位介绍mysql更改表引擎INNODB为MyISAM技巧. 常见的mysql表引擎 ...