react---HOC高阶组件初体验

HOC高阶组件初体验

什么是高阶组件:

简单的来说就是抽离具有相同逻辑或者相同展示的组件,用来提高组件复用率。

从本质上来讲高阶组件就是一个函数。这个函数接收了一个组件,并返回一个新的组件,返回的这个新组件可以对属性进行包装,也可以重写部分生命周期

简单案例

这是利用react脚手架创建的简单案例

入口文件index.js

import ReactDOM from 'react-dom'
import React from 'react'
import App from './App.jsx'
ReactDOM.render(<App/>,document.getElementById('root'))

APP组件App.jsx

import React, { Component } from 'react';
//第一步:创建一个高阶组件,传入一个组件,返回一个新的组件
const withHighOrder = (Component) => {
    //将传入组件的原有的属性作为参数重新传入新的组建中去
    const NewComponent = (props) => { 
        //利用ES6 ...属性扩散的新特性,将属性全部接受,并传入一个新的属性
        return <Component {...props} name="重新包装给定的新属性"></Component>
    }
    return NewComponent
}
class App extends Component {
    render() {
        return (
            <div>
                <h1>react高阶组件学习</h1>
                {/* 第三步:接收传递进来的属性,根据需要去使用 */}
                {this.props.name}
            </div>
        );
    }
}
//第二步,给创建的高阶组件传递需要重新包装的属性,这里是给App组件重新包装
export default withHighOrder( App ) ;

最终效果:

这里的话我大概总结一下简单高阶组件创建步骤:

  1. 定义一个高阶组件,给高阶组件传入需要重新包装的组件作为参数
  2. 在高阶组件内部创建一个新的组件,并将传入的组件的属性,传递参数,返回的新组建中重新包装需要给定的新的属性
  3. 高阶函数最后返回的是一个已经被包装过的新的组件
  4. 将我们需要包装的App组件作为参数,传递给高阶函数withHighOrder(App)
  5. 最后在需要的位置去应用传递进来的新属性

注意点:

  • 高阶组件命名一般以with开头
  • 千万不能忘记利用{...props}进行属性传递,不然新的包装还没用上,旧的属性也没得用
  • 一定要记得高阶函数最后的返回return NewComponent
  • 这里的话我没有去给App设立原有的属性,需要给App设立原有属性的话可以通过入口文件index.js中的<App/>给他传递你想要的属性

重写生命周期函数

刚刚的话我们这个简单的案例只是将组件重新包装了一下,给他传递了新的属性,接下来的话就是利用高阶函数的特性,给这个组件重写生命周期,同是我们可以达到链式调用的目的

先单独把重写生命周期函数这一块的高阶组件代码列出来

const withLifeCycle = (Component) => {
    //创建新的组件,重写生命周期并返回
    class NewComponent extends React.Component{
        //重写componentDidMount方法
        componentDidMount(){
            console.log('重写生命周期函数')
        }
        render(){
            return <Component {...this.props}></Component>
        }
    }
    return NewComponent
}

这里的话就是重写组件生命周期的高阶组建的代码内容,在最外层创建这个高阶函数,里面再创建一个新的class组件,在class组件中重写生命周期

最后通过刚才的方式我们再把新的组件暴露出去 withLifeCycle(App)就可以重写App的生命周期函数了,当然,如果我们原来就有过componentDidMount生命周期函数,也会先被执行

链式调用

使用情况如下:

  1. 编写一个高阶组件进行属性的添加
  2. 编写一个高阶组件编写生命周期
  3. 然后将以上两个高阶组件进行链式调用

现在的话我们就已经拥有了以上两点,属性和生命周期都可以进行更改,可以直接通过链式调用withLifeCycle( withHighOrder( App )) 因为withHighOrder( App )返回的还是一个组件,那么withLifeCycle()还是可以调用其返回的组件,这就实现了链式调用

完整App.jsx代码如下:

import React, { Component } from 'react';
//第一步:创建一个高阶组件,传入一个组件,返回一个新的组件
const withHighOrder = (Component) => {
    //将传入组件的原有的属性作为参数重新传入新的组建中去
    const NewComponent = (props) => { 
        //利用ES6 ...属性扩散的新特性,将属性全部接受,并传入一个新的属性
        return <Component {...props} name="重新包装给定的新属性"></Component>
    }
    return NewComponent
}
//创建新的高阶组件,重写生命周期
const withLifeCycle = (Component) => {
    //创建新的组件,重写生命周期并返回
    class NewComponent extends React.Component{
        //重写componentDidMount方法
        componentDidMount(){
            console.log('重写生命周期函数')
        }
        render(){
            return <Component {...this.props}></Component>
        }
    }
    return NewComponent
}
class App extends Component {
    
    render() {
        return (
            <div>
                <h1>react高阶组件学习</h1>
                {/* 第三步:接收传递进来的属性,根据需要去使用 */}
                {this.props.name}
            </div>
        );
    }
}
//第二步,给创建的高阶组件传递需要重新包装的属性,这里是给App组件重新包装
export default withLifeCycle( withHighOrder( App ));

效果图:

那么以上基本的高阶组件的使用就已经完成了。可以再对其进行扩展,之后的话我会专门再出一些经典的高阶组件使用的小案例,提供学习用。

装饰器的使用

其实我们会发现那么长一段的链式调用其实很复杂,也很绕,所以呢我们可以采用ES7提供的语法, 装饰器 ,专门来解决这种组件之间层层嵌套的问题,总结就是它是先走的,它放在谁的头上都是先执行装饰器函数然后再指定当前的函数,装个装饰器就可以对对象中的state,props进行修改,直接影响就是展示效果

create-react-app默认不支持装饰器的,需要做以下配置。

1.终端运行npm run eject,暴露项目的配置项,如果失败的话,则运行

git add .
git commit -m “commit”

2.安装babel插件

npm install --save-dev @babel/plugin-proposal-decorators

3.修改package.json文件的babel配置项

"babel": {
    "plugins": [
      ["@babel/plugin-proposal-decorators", { "legacy": true }]
    ],
    "presets": [
      "react-app"
    ]
  }

至此,就可以在我们的项目中使用装饰器了
附上利用装饰器的App.jsx简易版代码

import React, { Component } from 'react';
//第一步:创建一个高阶组件,传入一个组件,返回一个新的组件
const withHighOrder = (Component) => {
    //将传入组件的原有的属性作为参数重新传入新的组建中去
    const NewComponent = (props) => { 
        //利用ES6 ...属性扩散的新特性,将属性全部接受,并传入一个新的属性
        return <Component {...props} name="重新包装给定的新属性"></Component>
    }
    return NewComponent
}
//创建新的高阶组件,重写生命周期
const withLifeCycle = (Component) => {
    //创建新的组件,重写生命周期并返回
    class NewComponent extends React.Component{
        //重写componentDidMount方法
        componentDidMount(){
            console.log('重写生命周期函数')
        }
        render(){
            return <Component {...this.props}></Component>
        }
    }
    return NewComponent
}
@withHighOrder
@withLifeCycle
class App extends Component {
    
    render() {
        return (
            <div>
                <h1>react高阶组件学习</h1>
                {/* 第三步:接收传递进来的属性,根据需要去使用 */}
                {this.props.name}
            </div>
        );
    }
}
//第二步,给创建的高阶组件传递需要重新包装的属性,这里是给App组件重新包装
export default App ;

利用了装饰器我们在最后就不需要再一长串的withLifeCycle( withHighOrder( App ))去调用了,只需要在我们需要调用高阶函数的组件前去调用即可。这里要注意,一定要先声明高阶函数再去调用。不可以@高阶组件都从上到下出来了,高阶组件的内容还在更下面。这样是访问不到高阶组件的。

那到这里的话高阶组件的基本几个知识点就已经讲完了,到后面有机会的话我再出几个高阶组件的案例,简单的实际去用上这个高阶组件。

发布了2 篇原创文章 · 获赞 0 · 访问量 19

猜你喜欢

转载自blog.csdn.net/clylover/article/details/105277795