zoukankan      html  css  js  c++  java
  • React HOC

    在React官网文档学习React HOC,整个看了一遍还是云里雾里的,于是按照官网文档,自己动手实践一下。官网地址:React 高阶组件

    定义:高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件

    使用高阶组件(HOC)解决交叉问题

    假设有两个组件,CommentList组件从外部数据源订阅数据并渲染评论列表,BlogPost组件是一个订阅单个博客文章的组件,该组件遵循类似的模式,即在componentDidMount中添加事件处理函数订阅数据,在componentWillUnmount中清除事件处理函数,两个组件的事件处理函数内容相同。两个组件的区别在于:从数据源订阅的数据不同,并且渲染格式不同。(代码见React官网)
    由此,可以将两个组件中相同的逻辑部分提取到一个高阶组件,该高阶组件能够创建类似 CommonList 和 BlogPost 从数据源订阅数据的组件 。该组件接受一个子组件作为其中的一个参数,并从数据源订阅数据作为props属性传入子组件。该高阶组件命名为WithSubscription。

    import DataSource from '../DataSource'
    let withSubscription = (WrappedComponent, selectData) => {
        // ……返回另一个新组件……
        return class extends React.Component {
            constructor(props) {
                super(props);
                this.handleChange = this.handleChange.bind(this);
                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属性传递给原组件
                const style = {
                    'marginBottom':'30px'
                }
                return(
                    <div style={style}>
                        <div>This is a HOC Component...</div>
                        <WrappedComponent data={this.state.data} {...this.props} />
                    </div>
                );
            }
        };
    }
    export default withSubscription;
    

    高阶组件既不会修改原组件,也不会使用继承复制原组件的行为。相反,高阶组件是通过将原组件包裹(wrapping)在容器组件(container component)里面的方式来组合(composes) 使用原组件。高阶组件就是一个没有副作用的纯函数。
    高阶组件接收容器组件的所有props属性以及一个新的 data属性,并将从数据源订阅的数据用 data 属性渲染输出内容。高阶组件并不关心数据是如何以及为什么被使用,而被包裹组件也不关心数据来自何处。

    高阶组件使用

    ./pages/index.js
    import React from 'react'
    import HOCList from '../components/HOCList';
    import CommentList from '../components/CommentList';
    import BlogPost from '../components/BlogPost';
    import withSubscription from '../components/WithSubscription/index'
    
    const CommentListWithSubscription = withSubscription(
        CommentList,
        (DataSource) => DataSource.getComments()
    );
    
    const BlogPostWithSubscription = withSubscription(
        BlogPost,
        (DataSource, props) => DataSource.getBlogPost(props.id)
    );
    export default class extends React.Component {
        constructor(props) {
            super(props);
        }
        componentDidMount() {
        }
    
        render() {
            const style = {
                '100%',
                'text-align': 'center',
                title:{
                    color:'red'
                }
            }
            return (
                <div style={style}>
                    <h1 style={style.title}>hello hoc</h1>
                    <CommentListWithSubscription />
                    <BlogPostWithSubscription />
                </div>
            );
        }
    }
    

    CommentListWithSubscription的第一个参数是包裹组件(wrapped component),第二个参数会从 DataSource和当前props即高阶组件的props属性中检索需要的数据。
    当 CommentListWithSubscription 和 BlogPostWithSubscription 渲染时, 会向CommentList 和 BlogPost 传递一个 data props属性,该 data属性的数据包含了从 DataSource 检索的最新数据。

    官网的示例代码不完全,为了更好地看到运行结果,对代码做一些修改:

    • 另外创建数据源DataSource:
    ./components/DataSource.js
    let DataSource = {
        getComments: () => {
            return [
                'comment1', 'comment2', 'comment3'
            ]
        },
        getBlogPost: () => {
            return 'BlogPost Contents';
        },
        addChangeListener: () => { console.log('addChangeListener') },
        removeChangeListener: () => { console.log('removeChangeListener') },
    }
    export default DataSource;
    
    • 两个被包裹组件只负责对数据源的展示:
    //.components/BlogPost/index.js
    import React from 'react'
    import { Input,Button } from 'antd'
    
    const { TextArea } = Input;
    export default class extends React.Component {
      render() {
          return (
              <div>
                  <TextArea value={this.props.data} />
              </div>
          );
      }
    }
    
    //.components/BlogPCommentListst/index.js
    import React from 'react'
    
    export default class extends React.Component {
        render() {
            return (
                <div>
                    {this.props.data.map((value) => (
                        <div comment={value} key={value} >{value}</div>
                    ))}
                </div>
            );
        }
    }
    

    运行结果:http://localhost:3000/
    localhost:3000

    完整源码地址:https://github.com/wuhuaranran/myHOC

  • 相关阅读:
    Google Dremel 原理 如何能 3 秒分析 1PB
    [转]Git详解之一 Git起步
    [转] SharePoint 2013 安装图解
    Fixing an incomplete VM that’s stuck in the Creating state
    [转] Exchange 2013 安装部署详解
    NewSQL为何使传统关系数据库黯然失色?
    [转]盘点Google Reader以外的RSS阅读器
    2013年中国数据库大会PPT
    SCDPM 2012 详细讲解
    [转]SharePoint 2013配置开发环境,需安装VS2012插件
  • 原文地址:https://www.cnblogs.com/chaoxiZ/p/9956806.html
Copyright © 2011-2022 走看看