hoc_hocking - CSDN
  • 很多人看到高阶组件(HOC)这个概念就被吓到了,认为这东西很难,其实这东西概念真的很简单,我们先来看一个例子。 现在如果我想给这个 add 函数添加一个输出结果的功能,那么你可能会考虑我直接使用 console.log ...

    很多人看到高阶组件(HOC)这个概念就被吓到了,认为这东西很难,其实这东西概念真的很简单,我们先来看一个例子。
    在这里插入图片描述
    现在如果我想给这个 add 函数添加一个输出结果的功能,那么你可能会考虑我直接使用 console.log 不就实现了么。说的没错,但是如果我们想做的更加优雅并且容易复用和扩展,我们可以这样去做:
    在这里插入图片描述
    其实这个做法在函数式编程里称之为高阶函数,大家都知道 React 的思想中是存在函数式编程的,高阶组件和高阶函数就是同一个东西。我们实现一个函数,传入一个组件,然后在函数内部再实现一个函数去扩展传入的组件,最后返回一个新的组件,这就是高阶组件的概念,作用就是为了更好的复用代码。

    其实 HOC 和 Vue 中的 mixins 作用是一致的,并且在早期 React 也是使用 mixins 的方式。但是在使用 class 的方式创建组件以后,mixins 的方式就不能使用了,并且其实 mixins 也是存在一些问题的,比如:

    隐含了一些依赖,比如我在组件中写了某个 state 并且在 mixin 中使用了,就这存在了一个依赖关系。万一下次别人要移除它,就得去 mixin 中查找依赖
    多个 mixin 中可能存在相同命名的函数,同时代码组件中也不能出现相同命名的函数,否则就是重写了,其实我一直觉得命名真的是一件麻烦事。。
    雪球效应,虽然我一个组件还是使用着同一个 mixin,但是一个 mixin 会被多个组件使用,可能会存在需求使得 mixin 修改原本的函数或者新增更多的函数,这样可能就会产生一个维护成本
    HOC 解决了这些问题,并且它们达成的效果也是一致的,同时也更加的政治正确(毕竟更加函数式了)

    展开全文
  • 11.高阶组件(HOC) 什么是HOC 怎么封装一个HOC HOC的小栗子 HOC的用法 深入博文推荐 1. 什么是HOC 高阶组件(HOC)不是React的API是一种基于组件的编程方法,是为了组件更好的复用而存在的。 高阶组件!!!就是一个函数...

    11.高阶组件(HOC)

    • 什么是HOC
    • 怎么封装一个HOC
    • HOC的小栗子
    • HOC的用法
    • 深入博文推荐

    1. 什么是HOC

    高阶组件(HOC)不是React的API是一种基于组件的编程方法,是为了组件更好的复用而存在的。

    高阶组件!!!就是一个函数 不要慌!

    比如获取博客信息列表组件和获取评论列表,虽然可能评论列表在博客信息列表之间有一些差距,比如博客可能有转发等功能,而评论列表可能要有自动获取焦点,保存点评人ID等功能,但是两者都有获取数据源,列表渲染等功能,因此可以将评论组件和博客查询组件封装起来,然后把一些公共的方法抽出来,抽到一个函数中

    Notes:

    组件和高阶组件之间的区别:

    1. 组件是通过props来渲染组件的UI, 就是props -> UI
    2. 高阶组件是通过组件和props产生特定的组件, 就是 Component -> Component

    2.怎么封装一个HOC

    看一个官网例子:
    // 此函数接收一个组件...
    function 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() {
          // ... 并使用新数据渲染被包装的组件!
          // 请注意,我们可能还会传递其他属性
          return <WrappedComponent data={this.state.data} {...this.props} />;
        }
      };
    }
    
    // BlogPost是一个自定义的组件
    
    
    主要参考 React深入系列
    1. 高阶组件的常用写法:

    属性代理: 相当于在我们在调用封装组件之前, 先加一层,处理我们需要做的事情,比如我们需要将添加和减少传入下一个组件的props等

    反向继承: 相当于该组件继承我们传入的组件,然后通过super来调用父类的render方法

    1. 高阶组件的功能

    2. 组合渲染: 通过高阶组件拼接多个组件 ✔

    3. 条件渲染: 根据传入条件按条件渲染组件 ✔

    4. 操作props: 增加或者减少传入组件的props ✔

    5. 获取refs: 通过refs获得组件对象 ×

    6. 状态管理: 通过HOC来绑定一些状态属性,双向绑定 ✔

    7. 操作state: 利用反向代理来操作原组件的state ✔

    ✔为已经理解的,×为不太懂的,之后补上

    3. 一个高阶组件小栗子

    双向绑定的例子详解:

    场景: 在定义表单的时候,经常需要获取输入的表单信息,但是react没有像vue一样的双向绑定的v-model的语法糖,因此需要通过value和onChange来转变input组件为受控组件。

    高阶组件上场: 如果每次都去这样添加一个state中的value和onChange方法,非常麻烦,因此可以把这个双向绑定的方法提出来!

    // App.js 
    import React from "react";
    import "./App.css";
    import Form from "./Component/Form";
    import { BindInputText } from "./Component/BindInput";
    
    class Index extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          formData: [],
          eventId: 1
        };
        // this.onChange.bind(this);
      }
      renderObj = elem => {
        let render = [];
        for (const key in elem) {
          if (elem.hasOwnProperty(key)) {
            render.push(
              <div>
                {key}-{elem[key]}
              </div>
            );
          }
        }
        return render;
      };
      // 用来显示表单内容(不是重点)
      renderFormData = () => {
        let { formData } = this.state;
        return formData.map((elem, index) => (
          <div key={`index-${index}`}>{this.renderObj(elem)}</div>
        ));
      };
      // 用来添加FormData
      addEvent(item) {
        this.setState(state => {
          let { formData, eventId } = state;
          formData.push({ ...item, id: eventId });
          eventId++;
          return {
            formData,
            eventId
          };
        });
      }
    
      render() {
        return (
          <div>
            <p>表格的双向绑定</p>
            <Form onSubmit={this.addEvent.bind(this)}>
              <BindInputText type="text" v_model="name" />
            </Form>
            {this.renderFormData()}
          </div>
        );
      }
    }
    
    export default Index;
    
    // Form.jsx 整个表单用于提交表单
    
    import React, { Component } from "react";
    import PropTypes from "prop-types";
    
    class Form extends Component {
    
      // childContextTypes来创建传到子组件中的this.context中传递的变量类型
      static childContextTypes = {
        model: PropTypes.object,
        changeModel: PropTypes.func
      };
    
      constructor(props) {
        super(props);
        this.state = {
          // 用来保存表单内填写的信息
          model: {}
        };
        this.changeModel = this.changeModel.bind(this);
        this.onSubmit = this.onSubmit.bind(this);
      }
    
      onSubmit(event) {
        const { onSubmit } = this.props;
        console.log(this.state.model);
        // console.log(this)
        console.log(onSubmit);
        if (typeof onSubmit === "function") {
          // 如果有传入的onSubmit就在执行onSubmit, 在执行完添加的功能后还要执行传入的方法
          onSubmit(this.state.model);
        }
      }
    
      changeModel(name, value) {
        this.setState({
          // 这个代码的意思在保留原来this.state.model的基础上
          // 再添加以name代表的值为key,值为value的一组键值对
          // 虽然...一般要array有用
          // 但是react中好像object也可以这么用
          model: {
            ...this.state.model,
            [name]: value
          }
        });
      }
      
      // 通过getChildContext将定义好类型的参数和函数传入子组件
      // 这里的参数的类型一定要和childContextTypes中定义的相同!!
      getChildContext() {
        const _this = this;
        return {
          model: _this.state.model,
          changeModel: _this.changeModel
        };
      }
    
      render() {
        return (
          <div>
            // this.props.children 就是这个组件中包裹的内容
            {this.props.children}
            <button onClick={this.onSubmit}>Submit</button>
          </div>
        );
      }
    }
    export default Form;
    
    // BindInput.jsx 绑定的Input组件
    
    import React, { Component } from "react";
    import { WidthDataBind } from "./WithDataBind";
    
    // 这里用的是装饰器的方法进行调用
    @WidthDataBind
    class BindInputText extends Component {
      render() {
        return (
          // 这个空的标签是Fragment,具体可以看官网
          <>
            // 这个this.props是从Form中的BindInputType传过来的参数
            <input {...this.props} />
          </>
        );
      }
    }
    
    export { BindInputText };
    
    // WithDataBind.jsx 用于添加双向绑定的高阶组件(详解)
    import React, { Component } from "react";
    import PropTypes from "prop-types";
    
    function WidthDataBind(WrapperComponent) {
      return class WithDataBind extends Component {
        static contextTypes = {
          model: PropTypes.object,
          changeModel: PropTypes.func
        };
    
        state = {
          value: this.props.value | ""
        };
    
        onChange(event) {
          // this.context就是刚才从父组件中传过来的context
          const { changeModel } = this.context;
          // props <BindInputText type="text" v_model="name" />
          // type="text" v_model="name"就是从BindInputText传过来的props
          const { v_model } = this.props;
          // 通过changeModel来改变Form中的model
          changeModel(v_model, event.target.value);
          this.setState({ value: event.target.value });
        }
    
        componentDidMount() {
          console.log(this.props.onSubmit);
        }
    
        render() {
          const props = this.props;
          //   console.log(this.context);
          const { model } = this.context;
          const { v_model } = this.props;
          // 这里就通过子组件中添加了props
          const newProps = {
            ...props,
            onChange: this.onChange.bind(this),
            value: model[v_model]
          };
          return (
            <>
              // WrapperComponent 是传入的组件
              // 完成从传入的组件到一个新的组件
              <WrapperComponent {...newProps} />
            </>
          );
        }
      };
    }
    
    export { WidthDataBind };
    
    

    4.怎么使用HOC

    // 调用方法1: 函数调用
    const newBlogPost = withSubscription(BlogPost, param)
    export {newBlogPost}
    
    // 调用方法2:  利用装饰器
    @withSubscription
    class BlogPost extends React.Component{}
    export {BlogPost}
    

    5. 参考资料

    本文主要参考博文:

    React深入系列:React深入系列: 从mixin->HOC->Hooks

    官网文档(HOC):React文档–HOC

    Notes:

    1. Context可以使用childContextTypes和getChildContext来向组件树的context传递变量
    2. HOC的用法包括装饰器法和函数调用法
    3. HOC主要是通过传入一个组件,然后将该组件进行一些操作再返回一个组件,是从Component -> Component
    4. 用this.props 和 this.context来获取传递的参数
    展开全文
  • React 高阶组件 HOC

    2019-05-10 23:34:55
    基本概念 在javascript中,高阶函数是以函数为参数,并返回值也是函数的函数。类似,高阶函数接受React组件作为参数,并且返回一个新的React组件。高阶组件本质上也是一个函数。 形式: const EnhancedComponent = ...

    基本概念

    在javascript中,高阶函数是以函数为参数,并返回值也是函数的函数。类似,高阶函数接受React组件作为参数,并且返回一个新的React组件。高阶组件本质上也是一个函数。
    形式:

    const EnhancedComponent = heigherComponent(WrappedComponent)
    
    

    使用场景

    1. 操作props,添加,删除,修改

    在被包装组件接受props前。高阶组件可以先拦截props,对其添加,删除,修改。

    // App.js
    import React, { Component } from 'react';
    import { MyComponentWithPersistenData } from './Children'
    class App extends Component {
      constructor(props) {
        super(props)
    
        this.state = {
        }
      }
      render() {
        return (
          <div>
            <MyComponentWithPersistenData></MyComponentWithPersistenData>
          </div>
        );
      }
    }
    
    export default App;
    // Children
    
    import React, { Component } from 'react'
    
    function withPersistenData(WrappedComponent){
        return  class Children extends Component {
            componentWillMount(){
                let data = 0;
                this.setState({
                    data
                })
            }
            render() {
              return (
                <WrappedComponent {...this.props} data={this.state.data}></WrappedComponent>
              )
            }
          }
    }
    class MyComponent extends Component{
        render(){
            return <div>
                       {this.props.data}
                   </div>
        }
    }
    export const MyComponentWithPersistenData = withPersistenData(MyComponent)
    

    2. 通过ref访问组件实例

    高阶组件通过ref获取被包装组件实例的引用,然后高阶组件就具备了直接操作被包装组件的方法和属性。但实际项目很少。

    // App
    import { MyComponentWithPersistenData , MyComponentWithref  } from './Children'
    
    <MyComponentWithref></MyComponentWithref>
    
    // Children
    function Withref(WrappedComponent){
        return class extends React.Component{
            constructor(props) {
              super(props)
            
              this.state = {
                 
              }
            }
            componentDidMount(){
                this.refs.wrap.handle()
            }
            render(){
                return <WrappedComponent ref="wrap" {...this.props}></WrappedComponent>
            }
        }
    }
    class MyComponent2 extends Component{
        handle = ()=>{
            alert("方法调用")
        }
        render(){
            return <div>
                       <button onClick={this.handle}>按钮</button>
                   </div>
        }
    }
    export const MyComponentWithref = Withref(MyComponent2)
    
    

    点击会触发handle的方法,高阶组件刷新页面的时候,组件中也componentDidMount调用包裹组件的方法。

    3. 组件状态提升

    无状态组件更容易复用。高阶组件可以通过将被包装组件的状态和相应的状态处理方法提升到高阶组件自身内部实现被包装组件的无状态化。比如,受控组件中状态维护放在高阶组件中

    // App
    import { MyComponentWithPersistenData , MyComponentWithref ,MyComponentControl } from './Children'
    <MyComponentControl></MyComponentControl>
    // Children
    function withControlState(WrappedComponent){
        return class extends React.Component {
            constructor(props) {
              super(props)
            
              this.state = {
                 value:''
              }
            }
            handleChange=(e)=>{
                this.setState({
                    value:e.target.value
                })
            }
            render(){
                const newProps = {
                    controlProps:{
                        value:this.state.value,
                        onChange:this.handleChange
                    }
                }
                return <WrappedComponent {...this.props} {...newProps}></WrappedComponent>
            }
        }
    }
    class ControlComponent extends React.Component{
        render(){
            return <div>
                    <input type="text" {...this.props.controlProps}/>
                    {this.props.controlProps.value}
            </div>
            
        }
    }
    export const MyComponentControl = withControlState(MyComponent3)
    

    以上App.js和Children.js文件

    • App.js
    import React, { Component } from 'react';
    import { MyComponentWithPersistenData , MyComponentWithref ,MyComponentControl } from './Children'
    class App extends Component {
      constructor(props) {
        super(props)
    
        this.state = {
        }
      }
      render() {
        return (
          <div>
            <MyComponentWithPersistenData></MyComponentWithPersistenData>
            <MyComponentWithref></MyComponentWithref>
            <MyComponentControl></MyComponentControl>
          </div>
        );
      }
    }
    
    export default App;
    
    
    • Children.js
    import React, { Component } from 'react'
    
    function withPersistenData(WrappedComponent){
        return  class Children extends Component {
            componentWillMount(){
                let data = 0;
                this.setState({
                    data
                })
            }
            render() {
              return (
                <WrappedComponent {...this.props} data={this.state.data}></WrappedComponent>
              )
            }
          }
    }
    function Withref(WrappedComponent){
        return class extends React.Component{
            constructor(props) {
              super(props)
            
              this.state = {
                 
              }
            }
            componentDidMount(){
                this.refs.wrap.handle()
            }
            render(){
                return <WrappedComponent ref="wrap" {...this.props}></WrappedComponent>
            }
        }
    }
    function withControlState(WrappedComponent){
        return class extends React.Component {
            constructor(props) {
              super(props)
            
              this.state = {
                 value:''
              }
            }
            handleChange=(e)=>{
                this.setState({
                    value:e.target.value
                })
            }
            render(){
                const newProps = {
                    controlProps:{
                        value:this.state.value,
                        onChange:this.handleChange
                    }
                }
                return <WrappedComponent {...this.props} {...newProps}></WrappedComponent>
            }
        }
    }
    class MyComponent extends Component{
        render(){
            return <div>
                       {this.props.data}
                   </div>
        }
    }
    class MyComponent2 extends Component{
        handle = ()=>{
            alert("方法调用")
        }
        render(){
            return <div>
                       <button onClick={this.handle}>按钮</button>
                   </div>
        }
    }
    class MyComponent3 extends React.Component{
        render(){
            return <div>
                    <input type="text" {...this.props.controlProps}/>
                    {this.props.controlProps.value}
            </div>
            
        }
    }
    export const MyComponentWithPersistenData = withPersistenData(MyComponent)
    
    export const MyComponentWithref = Withref(MyComponent2)
    
    export const MyComponentControl = withControlState(MyComponent3)
    

    4. 用其他元素包装

    只是在高级组件中外面嵌套一个div,加css样式,布局。这个就不演示了。

    如有问题,望斧正

    展开全文
  • 高阶组件 HOC

    2019-07-20 01:49:36
    A higher-order component (HOC) is an advanced technique in React for reusing component logic. a higher-order component is a function that takes a component and returns a new component. use compo...

    一、

    A higher-order component (HOC) is an advanced technique in React for reusing component logic.

    a higher-order component is a function that takes a component and returns a new component.

    use composition

     

    二、

    compose vs decorators

     

    三、

    When you apply a HOC to a component, though, the original component is wrapped with a container component. That means the new component does not have any of the static methods of the original component.

    import hoistNonReactStatic from 'hoist-non-react-statics';
    function enhance(WrappedComponent) {
      class Enhance extends React.Component {/*...*/}
      hoistNonReactStatic(Enhance, WrappedComponent);
      return Enhance;
    }

     

    react Hoc 组建

    1.connect

    react-redux

    2.react-sortable

    拖拽

    3.recompact

    通过使用此库提供的高阶组件,可以方便地让列表元素可拖动。

     

     

     

     

     

    转载于:https://www.cnblogs.com/shangyueyue/p/10607784.html

    展开全文
  • React 高阶组件(HOC)

    2017-11-22 16:55:23
    原文地址:...React 高阶组件(HOC) 背景 高阶组件的这种写法的诞生来自于社区的实践,目的是解决一些交叉问题(Cross-Cutti...
  • 组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。 具体而言,高阶组件是参数为组件,返回值为新组件的函数。 const ...
  • HOC是什么

    2020-06-07 16:15:12
    HOC 很多人看到高阶组件(HOC)这个概念就被吓到了,认为这东西很难,其实这东西概念真的很简单,我们先来看一个例子。 function add(a, b) { return a + b } 现在如果我想给这个 add 函数添加一个输出结果的功能...
  • Apple考虑到这一点,因此通过Ad Hoc来实现发布前的用户测试。从另一个角度讲也就是通过Ad Hoc 将未发布的App 给其他人提前免费使用。 关于Ad Hoc的使用其实很简单,在Apple Developer官网的页面上也有详细的介绍。...
  • 自组织网络(Ad hoc

    2016-10-05 09:39:09
    自组织网络(Ad Hoc)是一种移动通信和计算机网络相结合的网络,是移动计算机网络的一种,用户终端可以在网内随意移动而保持通信。作为一种多跳的临时性自治系统,在军事、民用、商用等许多重要领域都具有独特优势,...
  • 什么是Ad-hoc Query

    2016-11-01 16:03:37
    维基百科的介绍中说,Ad hoc本意在拉丁文中是“为了这个目的”,或者“仅仅如此”。但实际上,Ad hoc这个术语无论是在网络中还是数据库中都有相当的应用。我们现在就来分析分析这个Ad-hoc Query到底是什么东西。Ad-...
  • SQL Server 阻止了对组件 'Ad Hoc Distributed Queries'2009年08月28日 星期五 15:00SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT'OpenRowset/OpenDatasource' 的访问,因为此组件已作为此...
  • mesh和ADhoc区别

    2018-09-08 13:06:02
    adhoc网络和无线Mesh网络都采用分布式、自组织的思想形成网络,网络每个节点都具备路由功能,随时为其他节点的数据传输提供路由和中继服务。 adhoc网络主要侧重应用于移动环境中,确保网络内任意两个节点的可靠通信...
  • Ansible中有一个很重要的功能就是可以执行ad-hoc命令,可能有些人不懂ad-hoc这个词的意思,它表示即时的意思,或者说随意的意思。 与之相对的是ansible playbook功能,playbook适用于批量部署环境,一般不用经常...
  • Ad-hoc网络

    2015-10-02 16:38:31
    Ad Hoc结构是一种省去了无线中介设备AP而搭建起来的对等网络结构,只要安装了无线网卡,计算机彼此之间即可实现无线互联;其原理是网络中的一台计算机主机建立点到点连接,相当于虚拟AP,而其他计算机就可以直接通过...
  • Ansible Ad-Hoc命令集

    2017-12-10 15:52:05
    3.1 Ad-Hoc使用场景  所谓Ad-Hoc,简而言之是"临时命令",英文中作为形容词有"特别的,临时"的含义。Ad-Hoc只是官方对Ansible命令的一种称谓。  从功能上讲,Ad-Hoc是相对于Ansible-playbook而言的,Ansible提供两种...
  • React——高阶组件(HOC)

    2018-06-04 13:23:22
    HOC(High Order Component) 是 react 中对组件逻辑复用部分进行抽离的高级技术,但HOC并不是一个 React API 。 它只是一种设计模式,类似于装饰器模式。 具体而言,HOC就是一个函数,且该函数接受一个组件作为...
  • 简单来说高阶组件(HOC)就是一个函数,它接受一个组件作为参数然后返回一个新组件。HOC 主要用于组件之间逻辑复用。比如你写了几个组件,他们之间的逻辑几乎相同,就可以用 HOC 对逻辑进行封装复用。 本文主要分享...
  • Ad-Hoc(点对点)模式

    2016-09-05 10:22:29
    Ad-Hoc(点对点)模式:ad-hoc模式就和以前的直连双绞线概念一样,是P2P的连接,所以也就无法与其它网络沟通了。一般无线终端设备像PMP、PSP、DMA等用的就是ad-hoc模式。 在家庭无线局域网的组建,我想大家都知道...
  • 最近实验室做的一些工作需要使用lattepanda(类似增强的树莓派)并且使用其无线网卡的ad-hoc模式,并且实现多台lattepanda之间实现网络通信。 将路由设置为Ad-Hoc(点对点)模式下,由于Ad-hoc独特的无中心、自组织...
  • 组建Ad Hoc模式无线局域网 一、 实验目的: 掌握在没有无线访问接入点(Wireless Access Point,AP)的情况下,如何通过无线网卡直接组件建无线 局域网,实现移动网络中智能终端设备之间直接互连的方法。 二、实验...
1 2 3 4 5 ... 20
收藏数 33,386
精华内容 13,354
关键字:

hoc