欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

谈谈React中的Render Props模式

程序员文章站 2022-03-30 20:29:13
概述 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)是动态构建的。

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