React基础5:组件设计模式

2020-06-24  本文已影响0人  CC前端手记

React有这样两种组件设计模式,高阶组件和函数式组件。高阶组件是将需要复用的逻辑提取到一个函数中,再去处理不同组件。函数作为子组件,是使用子组件来复用逻辑,然后从父组件传入不同内容。
我们来看下如何使用:

一、高阶组件

高阶组件是一个函数,它接受一个组件,返回一个新组件,可以提供可复用的功能。使用方法见下图:

// withToolTip.js
import React from 'react'
const withToolTip = (Component) => {
  class HOC extends React.Component {
    state= {
      showToolTip: false,
      content: ''
    }
    handleOver =(ev)=> this.setState({showToolTip: true, content: ev.target.innerText})
    handleOut = (ev)=> this.setState({showToolTip: false, content: ''})
    render(){
      return (
        <div onMouseOver={this.handleOver} onMouseOut={this.handleOut}>
          <Component action={this.state} />
        </div>
      )
    }
  }
  return HOC
}
export default withToolTip;

// ItemA.jsx
import React, {Component} from 'react';
import withToolTip from './withToolTip'
const ItemA = (props) => {
  return (
    <div>
      <button type="btn">ToolTipA</button>
      {props.action.showToolTip && (
        <span>
          {props.action.content}
        </span>
      )}
    </div>
  )
}
export default withToolTip(ItemA);

// ItemB.jsx
import React, { Component } from 'react';
import withToolTip from './withToolTip';
const ItemA = (props) => {
  return (
    <div>
      <button type="btn">ToolTipB</button>
      {props.action.showToolTip && (
        <span>
          {props.action.content}
        </span>
      )}
    </div>
  )
}
export default withToolTip(ItemB);

// App.js
import React, {PureComponent} from 'react';
import ItemA from './component/hoc/itemA';
import ItemB from './component/hoc/itemB';
class App extends PureComponent {
  constructor(props){
    super(props);
    this.state = {
      listData: [
        {
          id: 1,
          name: 'name1'
        },
        {
          id: 2,
          name: 'name2'
        }
      ]
    }
    ...
  }
  render(){
    return (
      <>
        <ItemA />
        <ItemB />
      </>
    )
  }
}
export default App;

总结一下例子中的基本用法:

  1. 父组件App引入两个子组件——ItemA和ItemB。
  2. ItemA和ItemB分别import withToolTip,并将组件ItemA/B作为参数返回新函数withToolTip(ItemA/B)。
  3. 将可复用的功能写在withToolTip函数中:定义方法名为withToolTip,将Component作为参数,返回withToolTip方法。在方法内部,定义类组件HOC并返回。在类组件HOC中定义state和渲染组件。

二、函数作为子组件

函数作为子组件,是使用子组件处理复用逻辑,然后从父组件传入不同内容。基本用法是:

  1. 定义子组件:
render(){
  return (
    <div>{this.props.render(this.state)}</div>
  )
}
  1. 使用函数作为Props
<RenderPropComponent render = { (state)=>(
  <div>content</div>
)} />

接下来,我们将上文高阶组件的例子改造成函数作为子组件的使用方式:

  1. withToolTip.js文件中,去掉const withToolTip = (Component) => {}一层;并且将<Component action={this.state} />替换为{this.props.render(this.state)}
  2. 新建ItemC.jsx组件,这里和ItemA/B的区别主要是:
    在组件内,直接使用withToolTip组件,并将页面结构放在render中;
    将props.action.xxx的props.action去掉;
    直接返回ItemC组件。
import React, {Component} from 'react';
import withToolTip from './withToolTip';
const ItemC = (props) => {
  return (
    <div>
      <WithToolTip render= {
          <div>
            <button type="btn">ToolTipA</button>
            {showToolTip && (
              <span>{content}</span>
            )}
          </div>
      } />
    </div>
  );
}
export default ItemC;

其中,引用<WithToolTip />组件部分,也可以使用下面的写法:

<WithToolTip>
  { (showToolTip, content)=>(
    <div>
      <button type="btn">ToolTipA</button>
      {showToolTip && (
         <span>{content}</span>
      )}
    </div>
) }
</WithToolTip>
  1. withToolTip.js文件修改,也要去掉const withToolTip=(Component)=>{}一层,将HOC改为WithToolTip;去掉return HOC;并且将withToolTip大写,如下:
import React from 'react'
class WithToolTip extends React.Component {
    state= {
      showToolTip: false,
      content: ''
    }
    handleOver =(ev)=> this.setState({showToolTip: true, content: ev.target.innerText})
    handleOut = (ev)=> this.setState({showToolTip: false, content: ''})
    render(){
      return (
        <div onMouseOver={this.handleOver} onMouseOut={this.handleOut}>
          <Component action={this.state} />
        </div>
      )
    }
}
export default WithToolTip;
上一篇下一篇

猜你喜欢

热点阅读