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

  • 相关阅读:
    手把手教你利用create-nuxt-app脚手架创建NuxtJS应用
    初识NuxtJS
    webpack打包Vue应用程序流程
    用选择器代替表格列的筛选功能
    Element-UI
    Spectral Bounds for Sparse PCA: Exact and Greedy Algorithms[贪婪算法选特征]
    Sparse Principal Component Analysis via Rotation and Truncation
    Generalized Power Method for Sparse Principal Component Analysis
    Sparse Principal Component Analysis via Regularized Low Rank Matrix Approximation(Adjusted Variance)
    Truncated Power Method for Sparse Eigenvalue Problems
  • 原文地址:https://www.cnblogs.com/chaoxiZ/p/9956806.html
Copyright © 2011-2022 走看看