可复用 React 的 HOC 以及的 Render Props
重复是不可能的,这辈子都不可能写重复的代码
当然,这句话分分钟都要被产品(领导)打脸,真的最后一次改需求,我们烦恼于频繁修改的需求
虽然我们不能改变别人,但我们却可以尝试去做的更好,我们需要抽象,封装重复的功能或者逻辑,而不是老旧的重复着机械的复制粘贴修改
那么我们如何去封装 React 中的组件以及逻辑呢?
这次我们来讲讲 React 里的高级组件
React 高级组件有两种方式:
- 使用高阶组件( Higher Order Component ==> HOC )
- 子组件作为函数的模式( Render Props )
高阶组件
首先来说说高阶组件,它不是 React 的提供的 API,它是模式,一种增强组件的模式,简单来说其实就是高阶函数,高阶函数大家应该不陌生
高阶函数 : 把函数作为参数传入,返回一个新的函数,这样的函数称为高阶函数
而所谓的高阶组件也就是传入一个现有组件作为参数,返回一个新的组件,高阶租价也分为代理方式和继承方式
我们先来看看一个简单的 HOC :
import React from 'react';
function addNameProp(WrapperComponent) {
return class extends React.Component {
render() {
const { name, ...props } = this.props;
return <WrapperComponent {...props} name={name || 'cnyballk'} />;
}
};
}
export default addNameProp;
在上面的代码里我们定义了一个 addNameProp。 函数,它的作用就是为没有传入 name 的 prop 传入的组件添加一个 name 的 prop ,然后渲染出来
这个高阶组件就完成了对传入组件的增强,这也是一个代理方式的高阶组件,
那么继承方式是怎么样的呢
import React from 'react';
function addNameProp(WrapperComponent) {
return class extends WrapperComponent {
render() {
this.props = {
...this.props,
name: this.props.name || 'cnyballk',
};
return super.render();
}
};
}
export default addNameProp;
和上面的高阶组件 一样的效果,而继承模式和代理模式最大的区别就是一个是返回传入的组件,一个是调用继承的父组件的 render 方法
⚠️ 在代理模式下 WrapperComponent 经历了完整的生命周期,返回的组件也有一次完整的生命周期,而继承模式 则是调用了 WrapperComponent 的 render ,只有返回的组件的一个生命周期
如果我们用过 react-redux 的 connect 也就知道 connect 也是一个代理模式的高阶组件
⚠️ 高阶组件可以这么使用
@Wrapper
class Index extends Component {
...略
}
emmmm...这个涉及到 js 的装饰器,各位自己去搜来学习哈
Render Props
那么我们已经认识了高阶组件的重用方法,也认识到了高阶组件的优点。
但是高阶组件的缺点是什么呢?
相信你们也能看到了,我们传递一个 name 的 Prop ,那是不是得传入的组件能够处理才可以,而且还有命名的冲突危险,毕竟有些组件的 props 命名各有不同,或者说子组件需要同一份数据处理方式却不一样,所以说这个时候就不适用 HOC 了
HOC 对于使用者来说是一个黑盒,还需要去看他们的实现
而 Render Props 则是 数据给你,其他的你自己来
我们来看一个简单的例子
import React from 'react';
class AddNameProp extends React.Component {
render() {
const name = 'cnyballk';
return this.props.children(name);
}
}
export default AddNameProp;
简单的使用
<AddNameProp>{name => <div>我叫 {name}</div>}</AddNameProp>
想传递给组件
<AddNameProp>
{name =>
<Hello name={name}/>;
}
</AddNameProp>
或者是其他的 prop 名
<AddNameProp>
{name =>
<Hello myName={name}/>;
}
</AddNameProp>
我们可以看到,这个方式很灵活,因为子组件是一个函数,一切皆有可能,但是 Render Props 也有缺点就是难以做性能优化,高阶组件可以利用 SCU 来避免重复渲染。虽然这样,,Render Props 却是一个非常好(牛逼)的一个模式,我很喜欢
Render Props VS HOC
我们能够清楚的明白,HOC是一种粗粒度的代码复用,而Render Props是一种细粒度的复用,他们可以互换,我们什么时候用HOC,什么时候用Render Props相信大家也差不多清楚了
小结
本文介绍了 React 的高级组件的两个方式,各有优缺点,但它们都是为了重用代码,我们可以自己选择喜欢的模式去做,但是不要复制粘贴了,感受封装复用的力量
高阶组件代理模式可以更好的控制和实现,继承模式则可以控制特定组件的生命周期,与高阶组件相比, Render Props 模式更加灵活,有函数,我们可以更自由
可复用 React 的 HOC 以及的 Render Props的更多相关文章
- React高阶组件 和 Render Props
高阶组件 本质 本质是函数,将组件作为接收参数,返回一个新的组件.HOC本身不是React API,是一种基于React组合的特而形成的设计模式. 解决的问题(作用) 一句话概括:功能的复用,减少代码 ...
- [React] Use Prop Collections with Render Props
Sometimes you have common use cases that require common props to be applied to certain elements. You ...
- 学习React系列(十)——Render Props
解决问题:将行为封装,供多个组件使用(在多个组件之间分享某段代码) 组件中的props属性中包含一个"render"属性(该属性为一个返回值为元素的方法),然后在该组件的rende ...
- React-代码复用(mixin.hoc.render props)
前言 最近在学习React的封装,虽然日常的开发中也有用到HOC或者Render Props,但从继承到组合,静态构建到动态渲染,都是似懂非懂,索性花时间系统性的整理,如有错误,请轻喷~~ 例子 以下 ...
- React中render Props模式
React组件复用 React组件复用的方式有两种: 1.render Props模式 2.高阶组件HOC 上面说的这两种方式并不是新的APi. 而是利用Raect自身的编码特点,演化而来的固定编码写 ...
- React Render Props 模式
概述 Render Props模式是一种非常灵活复用性非常高的模式,它可以把特定行为或功能封装成一个组件,提供给其他组件使用让其他组件拥有这样的能力,接下来我们一步一步来看React组件中如何实现这样 ...
- React 之 render props 的理解
1.基本概念 在调用组件时,引入一个函数类型的 prop,这个 prop定义了组件的渲染方式. 2.回调渲染 回顾组件通信的几种方式 父-> 子 props 子-> 父 回调.消息通道 任 ...
- [Recompose] Refactor React Render Props to Streaming Props with RxJS and Recompose
This lesson takes the concept of render props and migrates it over to streaming props by keeping the ...
- render props的运用
2020-04-03 render props的运用 术语 “render prop” 是指一种在 React 组件之间使用一个值为函数的 prop 共享代码的简单技术 通常的 这个值为函数的prop ...
随机推荐
- SigmoidCrossEntropyLoss
http://blog.csdn.net/u012235274/article/details/51361290
- [转]怎么样快速入门AngularJS?
本文转自:http://www.ngnice.com/posts/205af1ea1e13d2 怎么样快速学习AngularJS? 相信很多初学者都有过或者类似的疑问,其实这个问题没有标准的答案,每个 ...
- [RadControl] RadCartesianChart-功能強大圖表控件
由於最近做了一些統計的圖表分析,須使用到RadCartesianChart控件,因此就在這分享給大家順便為自己學習紀錄一下. 在介紹RadCartesianChart控件前,先看一下我所使用的到的功能 ...
- PHP中的header()函数
PHP header 函数的用法及其注意事项 void header ( string $string [, bool $replace = true [, int $http_response_co ...
- [转]png图片压缩大小但是不改变透明部分
降低PNG图片存储大小方法,图片压缩方法,如何降低PNG图片存储大小?前提是分辨率和尺寸大小不变,图形的透明部分不变.请看如下办法,亲测可用. 1. 将PNG图片用PS打开. 2. 图像-模式-8位/ ...
- 连接字符串(web.config)
data source=ip; initial catalog=db1; user id=sa; password=*** <connectionStrings> <add name ...
- CSS的框模型(div)与边距(margin、padding)
所谓框模型,例如div标签,你就可以直接把它理解成一个相框. 这个相框里面的相片有高度和宽度,框本身也有一定的宽度.相框和别的相框之间,还有一定的边距. div设置常见属性 border:边框 pad ...
- JS的定时到底有多不准
博客逐步迁移到,独立博客,原文地址,http://www.woniubi.cn/js_hide_tab_setinterval/ 我们一直都在说,JS的定时非常的不准确,但是很少有人去验证他,今天我就 ...
- Debug view 是个好工具
有时候不用 VS 调试, 在 代码里面加入 Debug.Writeline(" Debug information!!"); 这个时候打开 debug view 就可以检测出输出 ...
- android 屏幕单击位置测试
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools= ...