React组件复用的发展史

这篇博客探讨了React组件复用的发展历程,从废弃的Mixins,到高阶组件(HOC)、Render Props,最后到现代的Hooks。文章详细介绍了每种方法的实现、优缺点及注意事项,强调了Hooks如何简化组件状态管理和副作用处理,并遵循了React的组合哲学。
摘要由CSDN通过智能技术生成

Mixins

React Mixin通过将共享的方法包装成Mixins方法,然后注入各个组件来实现,官方已经不推荐使用,但仍然可以学习一下,了解为什么被遗弃。

React MiXin只能通过React.createClass()来使用,如下:

const mixinDefaultProps = {
   }
const ExampleComponent = React.createClasss({
   
  mixins: [mixinDefaultProps],
  render: function(){
   }
})

Mixins实现

import React from 'react'

var createReactClass = require('create-react-class')

const mixins = {
   
  onMouseMove: function(e){
   
    this.setState({
   
      x: e.clientX,
      y: e.clientY
    })
  }
}

const Mouse = createReactClass({
   
  mixins: [mixins],
  getInitialState: function() {
   
    return {
   
      x: 0,
      y: 0
    }
  },
  render() {
   
    return (<div onMouseMove={
   this.onMouseMove} style={
   {
   height: '300px'}}>
      <p>the current mouse position is ({
   this.state.x},{
   this.state.y})</p>
    </div>)
  }
})

Mixins问题

  • Mixins引入了隐式的依赖关系

你可能会写一个有状态的组件,然后你的同事可能添加一个读取这个组件statemixin。几个月之后,你可能希望将该state移动到父组件,以便与其兄弟组件共享。你会记得更新这个mixin来读取props而不是state吗?如果此时,其它组件也在使用这个mixin呢?

  • Mixins引起名称冲突

无法保证两个特定的mixin可以一起使用。例如,如果FluxListenerMixinWindowSizeMixin都定义来handleChange(),则不能一起使用它们。同时,你也无法在自己的组件上定义具有此名称的方法。

  • Mixins导致滚雪球式的复杂性

每一个新的需求都使得mixins更难理解。随着时间的推移,使用相同mixin的组件变得越来越多。任何mixin的新功能都被添加到使用该mixin的所有组件。没有办法拆分mixin的“更简单”的部分,除非或者引入更多依赖性和间接性。逐渐,封装的边界被侵蚀,由于很难改变或者删除现有的mixins,它们不断变得更抽象,直到没有人了解它们如何工作。

高阶组件

高阶组件(HOC)是React中复用组件逻辑的一种高级技巧。HOC自身不是React API的一部分,它是一种基于React的组合特性而形成的设计模式。

高阶组件是参数为组件,返回值为新组件的函数

组件是将props转换为UI,而高阶组件是将组件转换为另一个组件。

const EnhancedComponent = higherOrderComponent(WrappedComponent)

HOC的实现

  • Props Proxy: HOC对传给WrappedComponent的props进行操作
  • Inheritance Inversion HOC继承WrappedComponent,官方不推荐

Props Proxy

import React from 'react'

class Mouse extends React.Component {
   
  render() {
   
    const {
    x, y } = this.props.mouse 
    return (
      <p>The current mouse position is ({
   x}, {
   y})</p>
    )
  }
}

class Cat extends React.Component {
   
  render() {
   
    const {
    x, y } = this.props.mouse 
    return (<div style={
   {
   position: 'absolute', left: x, top: y, backgroundColor: 'yellow',}}>i am a cat</div>)
  }
}

const MouseHoc = (MouseComponent) => {
   
  return class extends React.Component {
   
    constructor(props) {
   
      super(props)
      this.state = {
   
        x: 0,
        y: 0
      }
    }
    onMouseMove = (e) => {
   
      this.setState({
   
        x: e.clientX,
        y: e.clientY
      })
    }
    render() {
   
      return (
        <div style={
   {
   height: '300px'}} onMouseMove={
   this.onMouseMove}>
          <MouseComponent mouse={
   this.state}/>
        </div>
      )

    }
  }
}

const WithCat = MouseHoc(Cat)
const WithMouse = MouseHoc(Mouse)

const MouseTracker = () => {
   
    return (
      <div>
        <WithCat/>
        <WithMouse/>
      </div>
    )
}

export default MouseTracker

请注意:HOC不会修改传入的组件,也不会使用继承来复制其行为。相反,HOC通过将组件包装在容器组件中来组成新组件。HOC是纯函数,没有副作用。

在Props Proxy模式下,我们可以做什么?

  • 操作Props

在HOC里面可以对props进行增删改查操作,如下:

参考 React面试题详细解答

  const MouseHoc = (MouseComponent, props) => {
   
    props.text = props.text + '--I can operate props'
   return class extends React.Component {
   
      render() {
   
        return (
          <div style={
   {
    height: '100%' }} onMouseMove={
   this.handleMouseMove}>
            <MouseComponent {
   ...props} mouse={
   this.state} />
          </div>
        )
      }
  }

  MouseHoc(Mouse, {
   
    text: 'some thing...'
  })
  • 通过Refs访问组件
  const MouseHoc = (MouseComponent) => {
   
    return class extends React.Component {
   
      ...
      render() {
   
        const props = {
    ...this.props, mouse: this.state }
        return (
          <div style={
   {
   height: '300px'}} onMouseMove={
   this.onMouseMove}>
            <MouseComponent {
   ...props}/>
          </div>
        )
      }
    }
  }

  class Mouse extends React.Component {
   
    componentDidMounted() {
   
      this.props.onRef(this)
    }
    render() {
   
      const {
    x, y } = this.props.mouse 
      return (
        <p>The current mouse position is ({
   x}, {
   y})</p>
      )
    }
  }

  const WithMouse = MouseHoc(Mouse)

  <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值