谈谈React中的Render Props模式

概述

Render Props模式是一种非常灵活复用性非常高的模式,它可以把特定行为或功能封装成一个组件,提供给其他组件使用让其他组件拥有这样的能力,接下来我们一步一步来看React组件中如何实现这样的功能。

简要介绍:分离UI与业务的方法一直在演进,从早期的mixins,到HOC,再到Render Prop,本文主要对比HOC,谈谈Render Props

1 . 早期的mixins

早期复用业务通过mixins来实现,比如组件A和组件B中,有一些公用函数,通过mixins剥离这些公用部分,并将其组合成一个公用集合,然后将这个集合传递给每个组件调用。

//公有的函数部分
const someMixins={
 printColor(){
 console.log(this.state.color);
 }
 printWeight(){
 console.log(this.state.weight);
 }
}
class Apple extends React.Component{
 //仅仅作为演示,mixins一般是通过React.createClass创建,并且ES6也没有key:value这种写法
 mixins:[someMixins]
 constructor(props){
 super(props);
 this.state={
  color:'red',
  weight:'100g'
 }
 this.printColor=this.printColor.bind(this);
 }
 render(){
 return <div className="m-box" onClick={this.printColor}>
    这是一个苹果
   </div>
 }
}
class Banana extends React.Component{
 mixins:[someMixins]
 constructor(props){
 super(props);
 this.state={
  color:'yellow',
  weight:'200g'
 }
 this.printColor=this.printColor.bind(this);
 }
 render(){
 return <div className="m-box" onClick={this.printColor}>
    这是一个香蕉
   </div>
 }
}

上述的例子中,Apple和Banana都具有printColor和printWeight方法,通过mixins分离公共业务。mixins已经在React16.0版本移除,这里仅仅做一个介绍。

2 . HOC

HOC简单理解就是组件工厂,接受原始组件作为参数,添加完功能与业务后,返回新的组件。下面来介绍HOC参数的几个例子。

(1)参数仅为原始组件,比如:

const redApple = withFruit(Apple);

(2)参数为原始组件和一个对象,比如:

const redApple = withFruit(Apple,{color:'red',weight:'200g'});

但是这种情况比较少用,如果对象中仅仅传递的是属性,其实完全可以通过组件的props实现值的传递,我们用HOC的主要目的是分离业务,关于UI的展示,以及一些组件中的属性和状态,我们一般通过props来指定比较方便

(3)参数为原始组件和一个函数,比如:

const redApp=withFruit(App,()=>{console.log('I am a fruit')})

这种是HOC的典型例子,原始组件参数表示UI部分,函数参数表示处理逻辑,在HOC工厂中进行耦合后生成新的组件。

(4)柯里化

最常见的是仅以一个原始组件作为参数,但是在外层包裹了业务逻辑,比如react-redux的conect函数中:

class Admin extends React.Component{

}
const mapStateToProps=(state)=>{
 return {
 };
}
const mapDispatchToProps=(dispatch)=>{
 return {

 }
}

const connect(mapStateToProps,mapDispatchToProps)(Admin)

这里不是严格的柯里化,但是思想是一样的,在HOC的工厂函数中在包一层父函数,用于指定业务逻辑。

3 . HOC的缺点

下面我们来看看HOC的缺点:

(1)难以溯源,且存在属性覆盖问题

如果原始组件A,先后通过工厂函数1,工厂函数2,工厂函数3….构造,最后生成了组件B,我们知道组件B中有很多与A组件不同的props,但是我们仅仅通过组件B,并不能知道哪个组件来自于哪个工厂函数。同时,如果有2个工厂函数同时修改了组件A的某个同名属性,那么会有属性覆盖的问题,会使得前一个工厂函数的修改结果失效。

(2)HOC是静态构建的

所谓静态构建,也就是说生成的是一个新的组件,并不会马上render,HOC组件工厂是静态构建一个组件,这类似于重新声明一个组件的部分。也就是说,HOC工厂函数里面的声明周期函数,也只有在新组件被渲染的时候才会执行。

(3)会产生无用的空组件

4. render props

class Cat extends React.Component {
 render() {
 const mouse = this.props.mouse;
 return (
  <img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} />
 );
 }
}

class Mouse extends React.Component {
 constructor(props) {
 super(props);
 this.handleMouseMove = this.handleMouseMove.bind(this);
 this.state = { x: 0, y: 0 };
 }

 handleMouseMove(event) {
 this.setState({
  x: event.clientX,
  y: event.clientY
 });
 }

 render() {
 return (
  <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>

  {/*
   Instead of providing a static representation of what <Mouse> renders,
   use the `render` prop to dynamically determine what to render.
  */}
  {this.props.render(this.state)}
  </div>
 );
 }
}

class MouseTracker extends React.Component {
 render() {
 return (
  <div>
  <h1>Move the mouse around!</h1>
  <Mouse render={mouse => (
   <Cat mouse={mouse} />
  )}/>
  </div>
 );
 }
}

上述是官网给出的例子,我们来看主要是部分是下面这两句:

Class Mouse extends React.component{
 ...
 {this.props.render(this.state)}
 ...
}

......
<Mouse render={mouse => (
   <Cat mouse={mouse} />
  )}/>

在使用Mouse组件的时候,通过一个render属性,传递一个可用组件Cat给父组件Mouse,而在Mouse组件中,可以将本身的state对象传递给Cat组件,Cat组件中的mouse属性的值与Mouse父组件中的state相同。

精简来说: 就是父组件可以将自己的state传递给子组件,而子组件可以根据父组件的state对象,来进行render。

这样做的好处是:

(1)不用担心props的命名问题

(2)可以溯源,子组件的props一定是来自于直接父组件

(3)是动态构建的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • React中的render何时执行过程

    我们都知道Render在组件实例化和存在期时都会被执行.实例化在componentWillMount执行完成后就会被执行,这个没什么好说的.在这里我们主要分析存在期组件更新时的执行. 存在期的方法包含: - componentWillReceiveProps - shouldComponentUpdate - componentWillUpdate - render - componentDidUpdate 这些方法会在组件的状态或者属性发生发生变化时被执行,如果我们使用了Redux,那么就只有

  • react实现pure render时bind(this)隐患需注意!

    pure render 我就不多说了,附上我另一片文章链接 react如何性能达到最大化(前传) 不论你用不用immutable,只要你想达到pure render,下面值得你注意! 一天我和往常一样,开开心心得写着react,用着@pureRender, export default class extends Component { ... render() { const {name,age} =this.state; return ( <div> <Person name={na

  • 谈谈React中的Render Props模式

    概述 Render Props模式是一种非常灵活复用性非常高的模式,它可以把特定行为或功能封装成一个组件,提供给其他组件使用让其他组件拥有这样的能力,接下来我们一步一步来看React组件中如何实现这样的功能. 简要介绍:分离UI与业务的方法一直在演进,从早期的mixins,到HOC,再到Render Prop,本文主要对比HOC,谈谈Render Props 1 . 早期的mixins 早期复用业务通过mixins来实现,比如组件A和组件B中,有一些公用函数,通过mixins剥离这些公用部分,并

  • react render props模式实现组件复用示例

    目录 一 render props的使用步骤 二 组件的复用 三 使用children名代替属性 一 render props的使用步骤 1 创建要复用的组件,在组件中提供要复用的状态逻辑代码2 将要复用的state作为方法的参数,暴露到组件外部 import React from "react"; import ReactDOM from "react-dom"; class App extends React.Component { render() { ret

  • 简单谈谈React中的路由系统

    React中的路由系统 提起路由,首先想到的就是 ASPNET MVC 里面的路由系统--通过事先定义一组路由规则,程序运行时就能自动根据我们输入的URL来返回相对应的页面.前端中的路由与之类似,前端中的路由是根据你定义的路由规则来渲染不同的页面/组件,同时也会更新地址栏的URL.本篇文章要介绍的是React中经常使用到的路由,react-router主要使用HTML5的history API来同步你的UI和URL. react-router的最新版本是v4.1.1,由于4.0版本和之间的版本A

  • React中关于render()的用法及说明

    目录 React中的render() 1.render() 2.当 render 被调用时 3.render() 函数应该为纯函数 4.如需与浏览器进行交互 5.在React.Component类 6.在react中触发render的有4条路径 7.生命周期流程图(来源于官网) React render在什么时候会被触发? 总结 React中的render() 1.render() 是 class 组件中唯一必须实现的方法 2.当 render 被调用时 它会检查 this.props 和 th

  • React 中state与props更新深入解析

    目录 正文 组件的 updater 处理 ClickCounter Fiber 的 update beginWork Reconciling children for the ClickCounter Fiber 处理 Span Fiber 的 update Reconciling children for the span fiber Effects list commit 阶段 应用 effects DOM updates 调用 Post-mutation 生命周期 正文 在这篇文章中,我使

  • 详细谈谈React中setState是一个宏任务还是微任务

    目录 前言 面试官的问法是否正确?§ React 是如何控制 setState 的 ?§ 未来会有异步的 setState§ 总结 前言 最近有个朋友面试,面试官问了个奇葩的问题,也就是我写在标题上的这个问题. 能问出这个问题,面试官应该对 React 不是很了解,也是可能是看到面试者简历里面有写过自己熟悉 React,面试官想通过这个问题来判断面试者是不是真的熟悉 React

  • 通过实例了解Render Props回调地狱解决方案

    简而言之,只要一个组件中某个属性的值是函数,那么就可以说该组件使用了 Render Props 这种技术.听起来好像就那么回事儿,那到底 Render Props 有哪些应用场景呢,咱们还是从简单的例子讲起,假如咱们要实现一个展示个人信息的组件,一开始可能会这么实现: const PersonInfo = props => ( <div> <h1>姓名:{props.name}</h1> </div> ); // 调用 <PersonInfo n

  • React中使用collections时key的重要性详解

    前言 大家应该都知道,在 React 中 render collections 的 items 时, Keys 扮演着重要的角色, 它直接决定接下来的 rendered 和 re-rendered,下面话不多说,来一起看看详细的介绍: React 不会 render 重复的 keys 为了彻底明白这个, 我们来声明一个这样的数组 const nums = [1, 2, 3, 5, 2]; // 它有两个元素的值是相等的 现在, 我们在 react 中来 render <ul> {nums.ma

  • React Render Props共享代码技术

    目录 介绍 使用 使用children prop代替render prop Render props 与 React.PureComponent 同时使用 注意 解决方案 介绍 Render Props是指在React组件之间使用一个值为函数的prop共享代码的技术 具有render prop的组件接受一个返回React元素的函数,并在组件内部通过调用此函数来实现自己的渲染逻辑 主要用于抽离逻辑,进行代码复用 使用 以官方文档的Mouse & Cat示例为例 创建Mouse组件,此组件仅用于提供

随机推荐