• 浅析为什么用高阶组件代替 Mixins


    转载来源 感谢分享

    Mixins 引入了无形的依赖

    • 应尽量构建无状态组件,Mixin 则反其道而行之
    • Mixin 可能会相互依赖,相互耦合,不利于代码维护
    • 不同的 Mixin 中的方法可能会相互冲突

    举个例子

    Mixins 有个主要用途是组件从其它数据源订阅数据:

    class CommentList extends React.Component {
      this.state = {
        // "DataSource" 就是全局的数据源
        comments: DataSource.getComments()
      }
    
      componentDidMount() {
        // 添加事件处理函数订阅数据
        DataSource.addChangeListener(this.handleChange);
      }
    
      componentWillUnmount() {
        // 清除事件处理函数
        DataSource.removeChangeListener(this.handleChange);
      }
    
      handleChange = () => {
        // 任何时候数据发生改变就更新组件
        this.setState({
          comments: DataSource.getComments()
        })
      }
    
      render() {
        return (
          <div>
            {this.state.comments.map((comment) => (
              <Comment comment={comment} key={comment.id} />
            ))}
          </div>
        )
      }
    }

    当多个组件共用此逻辑时,使用 高阶组件 来优化:

    const CommentListWithSubscription = withSubscription(
      CommentList,
      (DataSource) => DataSource.getComments()
    )
    
    const BlogPostWithSubscription = withSubscription(
      BlogPost,
      (DataSource, props) => DataSource.getBlogPost(props.id)
    )
    
    // 函数接受一个组件参数……
    function withSubscription(WrappedComponent, selectData) {
      // ……返回另一个新组件……
      return class extends React.Component {
        this.state = {
          data: selectData(DataSource, props)
        }
    
        componentDidMount() {
          // ……注意订阅数据……
          DataSource.addChangeListener(this.handleChange)
        }
    
        componentWillUnmount() {
          DataSource.removeChangeListener(this.handleChange)
        }
    
        handleChange = () => {
          this.setState({
            data: selectData(DataSource, this.props)
          })
        }
    
        render() {
          // ……使用最新的数据渲染组件
          // 注意此处将已有的props属性传递给原组件
          return <WrappedComponent data={this.state.data} {...this.props} />
        }
      }
    }

    高阶组件既不会修改 input 原组件,也不会使用继承复制 input 原组件的行为。相反,高阶组件是通过将原组件包裹(wrapping)在容器组件(container component)里面的方式来组合(composes)使用原组件。高阶组件就是一个没有副作用的纯函数。

    抽取状态

    说白了就是在无状态组件和其容器组件的关系中,通常让无状态组件不管理自己的状态,状态的管理交给外面的容器组件。

    react-redux 的 connect 函数就用来抽取状态,它返回一个高阶组件。

    假定你了解 Redux,那么可以看下 connect 的简易实现:

    const doNothing = () => ({})
    
    function connect(mapStateToProps=doNothing, mapDispatchToProps=doNothing) {
      return function(WarppedComponent) {
        class HOC extends React.Component {
          this.state = {}
    
          componentDidMount() {
            this.context.store.subscribe(this.onChange)
          }
    
          componentWillUmount() {
            this.context.store.unsubscribe(this.onChange)
          }
    
          // HOC 保证 Redux 上 Store 状态变化的时候驱动这个组件的更新
          onChange = () => this.setState({})
    
          render() {
            const store = this.centext.store
            // 执行 getState 得到 Redux Store 状态
            // 通过 dispatch 得到传递给 mapDispatchToProps 的 dispatch 方法
            const newProps = {
              ...this.props,
              ...mapStateToProps(store.getState()),
              ...mapDispatchToProps(store.dispatch)
            }
    
            return <WarppedComponent {...newProps} />
          }
        }
    
        // 创建新组件需要利用 Context 功能,所以定义了 types 属性,
        // 从 Context 中获取名为 store 的值
        HOC.contextTypes = { store.React.PropTypes.object }
    
        return HOC
      }
    }
  • 相关阅读:
    python使用tcp实现一个简单的下载器
    python中的tcp
    python使用udp实现聊天器
    python网络编程-udp
    python中的eval函数
    python文件
    python模块和包
    python异常处理
    python面向对象学习(七)单例
    python面向对象学习(六)类属性、类方法、静态方法
  • 原文地址:https://www.cnblogs.com/lanshengzhong/p/9391054.html
Copyright © 2020-2023  润新知