上海千语创想科技有限公司
 175-2108-6175
网站建设资讯详细

react高阶组件介绍

日期:2021-08-06  作者:千语创想  浏览:6336

React高阶组件是什么,高阶组件能干什么?

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

这是react官网给出的解释,也就是说,高阶组件就是接收一个组件,然后返回一个新组件。这是函数式编程的思想。那么高阶组件是如何实现的呢?俩种方法:属性代理和反向继承。

属性代理:实质就是通过包裹原来的组件来操作props;

import React, { Component } from 'react'

 

const HOC = (WrappedComponent) =>

  class WrapperComponent extends Component {

    render() {

      return <WrappedComponent {...this.props} />;

    }

}

//普通的组件

class WrappedComponent extends Component{

    render(){

        //....

    }

}

//高阶组件使用

export default HOC(WrappedComponent)

我们可以看到,原封不动的返回了WrappedComponent组件。


操作props:


我们看到之前要传递给被包裹组件WrappedComponent的属性首先传递给了高阶组件返回的组件(WrapperComponent),这样我们就获得了props的控制权(这也就是为什么这种方法叫做属性代理)。我们可以按照需要对传入的props进行增加、删除、修改(当然修改带来的风险需要你自己来控制)


const HOC = (WrappedComponent) =>

    class WrapperComponent extends Component {

        render() {

            const newProps = {

                name: 'HOC'

            }

            return <WrappedComponent

                {...this.props}

                {...newProps}

            />;

        }

    }

为被包裹组件(WrappedComponent)新增加了固定的name属性,因此WrappedComponent组件中就会多一个name的属性。


获取ref:在属性代理中,可以轻松的拿到被包裹的组件的实例引用(ref)


import React, { Component } from 'React';

 

const HOC = (WrappedComponent) =>

    class wrapperComponent extends Component {

        storeRef(ref) {

            this.ref = ref;

        }

        render() {

            return <WrappedComponent

                {...this.props}

                ref = {::this.storeRef}

            />;

        }

    }

wrapperComponent渲染接受后,我们就可以拿到WrappedComponent组件的实例,进而实现调用实例方法的操作(当然这样会在一定程度上是反模式的,不是非常的推荐)。


抽象state:属性代理的情况下,我们可以将被包裹组件(WrappedComponent)中的状态提到包裹组件中,一个常见的例子就是实现不受控组件到受控的组件的转变.


class WrappedComponent extends Component {

    render() {

        return <input name="name" {...this.props.name} />;

    }

}

 

const HOC = (WrappedComponent) =>

    class extends Component {

        constructor(props) {

            super(props);

            this.state = {

                name: '',

            };

 

            this.onNameChange = this.onNameChange.bind(this);

        }

 

        onNameChange(event) {

            this.setState({

                name: event.target.value,

            })

        }

 

        render() {

            const newProps = {

                name: {

                    value: this.state.name,

                    onChange: this.onNameChange,

                },

            }

            return <WrappedComponent {...this.props} {...newProps} />;

        }

    }


将不受控组件(WrappedComponent)成功的转变为受控组件.


反向继承:反向继承是指返回的组件去继承之前的组件


const HOC = (WrappedComponent) =>

  class extends WrappedComponent {

    render() {

      return super.render();

    }

  }

可以看见返回的组件确实都继承自WrappedComponent,那么所有的调用将是反向调用的(例如:super.render()),这也就是为什么叫做反向继承。


渲染劫持:渲染劫持是指我们可以有意识地控制WrappedComponent的渲染过程,从而控制渲染控制的结果。例如我们可以根据部分参数去决定是否渲染组件:


const HOC = (WrappedComponent) =>

  class extends WrappedComponent {

    render() {

      if (this.props.isRender) {

        return super.render();

      } else {

        return null;

      }

    }

  }

在反向继承中,我们可以做非常多的操作,修改state、props甚至是翻转Element Tree。反向继承有一个重要的点: 反向继承不能保证完整的子组件树被解析。


元素(element)是一个是用DOM节点或者组件来描述屏幕显示的纯对象,元素可以在属性(props.children)中包含其他的元素,一旦创建就不会改变。我们通过JSX和React.createClass创建的都是元素。

组件(component)可以接受属性(props)作为输入,然后返回一个元素树(element tree)作为输出。有多种实现方式:Class或者函数(Function)。

  所以, 反向继承不能保证完整的子组件树被解析的意思的解析的元素树中包含了组件(函数类型或者Class类型),就不能再操作组件的子组件了,这就是所谓的不能完全解析。


总的来说:


高阶组件属于函数式编程(functional programming)思想,对于被包裹的组件时不会感知到高阶组件的存在,而高阶组件返回的组件会在原来的组件之上具有功能增强的效果。而Mixin这种混入的模式,会给组件不断增加新的方法和属性,组件本身不仅可以感知,甚至需要做相关的处理(例如命名冲突、状态维护),一旦混入的模块变多时,整个组件就变的难以维护,也就是为什么如此多的React库都采用高阶组件的方式进行开发。


开发框架拓展


AVM(Application-View-Model)是千语创想推出的一个跨端高性能 JavaScript框架,更趋近于原生的编程体验,它提供简洁的模型来分离应用的用户界面、业务逻辑和数据模型,适合高度定制化的项目。AVM(千语创想 View Model)是千语创想基于标准H5子集设计的DSL中间语言编程框架,其可具备如下能力:

 

Virtual DOM:通过虚拟DOM,渲染到不同终端,充分尊重系统特性,为不同终端执行差异处理,实现高效渲染;

组件化:高可重用性、可组合性、可维护性的架构设计,隐藏了复杂的DOM结构和行为,让开发者专注于应用的功能和外观;

数据绑定:轻松将数据源绑定到应用用户界面,降低逻辑复杂性和开发难度;

状态管理和路由:有效分离用户界面和数据处理,实现项目的工程化管理;

类Vue语法和兼容React JSX,兼具Vue的轻巧和React的灵活性。

千语创想 DSL最终可编译为标准JS,通过DeepEngine渲染到app端和Web端,或者编译为微信小程序代码,用于微信小程序平台发布。


转载请注明来自:https://www.qianyuthink.com/news/7443.html

填写您的项目需求给我们

或者直接拨打 7×12小时一对一咨询电话

175 2108 6175

请填写需求信息,我们会在10分钟内与您取得联系

请认真填写需求信息,我们会在10分钟内与您取得联系

×
客服二维码
咨询技术总监
175-2108-6175
客服二维码
技术总监微信
客服二维码