React 高階組件

React高階組件

本文是學習慕課網 React高階組件課程 的筆記~css

1、什麼是React高階組件

高階組件就是接收一個組件做爲參數,而後返回一個新的組件。高階組件實際上是一個函數,並不僅是一個組件。react

2、入門Demo來認識高階組件

一、需求分析

加入有某需求:git

咱們對上圖進行組件拆分,能夠分爲外部modal提示框組件和內部信息兩個組件。github

外部modal組件是不變的,可是內部的內容,咱們可能在不一樣的地方會顯示不一樣的效果。以下圖。bash

因此咱們有必要去封裝一個外部的modal提示框組件,去包裹不一樣的內部組件。app

二、項目構建

// 建立一個空項目
create-react-app xxx
複製代碼

咱們新建幾個文件。函數

// A/index.js

import React from 'react';
import './index.css';

// 定義一個函數
// 傳入一個組件做爲參數
function A(WrappedComponent) {
  // 返回一個組件
  return class A extends React.Component {
    constructor (props) {
      super(props);
      this.state = {};
    }

    render () {
      return (
        <div className="a-container"> <div className="header"> <div className="title">提示</div> <div className="close">X</div> </div> <div> <!-- 在這裏使用一下 --> <WrappedComponent /> </div> </div>
      )
    }
  }
}

// 拋出函數
export default A

複製代碼

A組件就是咱們的外部Modal提示框組件。用來包裹咱們的內部組件。學習

咱們來實現B組件。ui

// B/index.js

import React from 'react';
import A from '../A/index.js';
import './index.css';


class B extends React.Component {
    render() {
        return (
            <div className="wrap"> <img src="https://raw.githubusercontent.com/freya0608/High-order-component/master/src/imgs/B.png" alt="" /> </div> ); } } <!--調用A()方法去包裹咱們的B組件。--> export default A(B); 複製代碼

最終實現效果爲:this

到此一個入門的高階組件實例就ok了。

總結:使用高階組件的方式:

第一種就是咱們上面的方法,第二種是利用裝飾器來實現,具體的配置你們網上能夠查到。

如今咱們又有了需求,就是B組件的內容,可能決定A組件的標題,因此這時候就須要咱們去經過B組件去傳值給A了。

// A/index.js

import React from 'react';
import './index.css';

// 這裏咱們返回一個匿名函數,接收傳遞得值
export default (title = '我是標題') => {

  // 而後返回一個函數,這個函數接收子組件 
  return (WrappedComponent) => {
    // 返回咱們的外部組件
    return class A extends React.Component {
      constructor (props) {
        super(props);
        this.state = {};
      }

      render () {
        return (
          <div className="a-container"> <div className="header"> <!--這裏使用咱們傳入的值--> <div className="title">{title}</div> <div className="close">X</div> </div> <div> <WrappedComponent /> </div> </div>
        )
      }
    }
  }
}
複製代碼
// B/index.js
import React from 'react';
import A from '../A/index.js';
import './index.css';
class B extends React.Component {
    render() {
        return (
            <div className="wrap"> <img src="https://raw.githubusercontent.com/freya0608/High-order-component/master/src/imgs/B.png" alt="" /> </div> ); } } <!-- 最主要是這裏 --> export default A('提示i')(B); 複製代碼

這樣咱們就實現了B給A組件傳值,來讓A組件能動態的改變某些地方了。

3、代理方式的高階組件

認識代理方式的高階組件咱們要從 prop、訪問ref、抽取狀態、包裹組件四個部分來認識。

  • props
// A/index

import React from 'react';
import './index.css';

export default (title = '我是標題') => {
  return (WrappedComponent) => {
    return class A extends React.Component {
      constructor (props) {
        super(props);
        this.state = {};
      }

      render () {
        // [1] 首先咱們能夠獲取到給最外層組件傳遞的props
        const prop = this.props;
        console.log(prop);

        
        return (
          <div className="a-container"> <div className="header"> <div className="title">{title}</div> <div className="close">X</div> </div> <div> <!--[2] 能夠傳遞下去,傳到B組件中--> <!--[3] 另外sex是新增的--> <WrappedComponent sex={'男'} {...this.props} /> </div> </div> ) } } } } 複製代碼
// B/index.js

import React from 'react';
import A from '../A/index.js';
import './index.css';
class B extends React.Component {
    render() {
        return (
            <div className="wrap"> <!--[1]在B組件中就能夠拿到經過A組件傳來的props--> 個人姓名: {this.props.name} 個人性別: {this.props.sex} <img src="https://raw.githubusercontent.com/freya0608/High-order-component/master/src/imgs/B.png" alt="" /> </div> ); } } export default A('提示i')(B); 複製代碼

在APP中咱們能夠設置props,傳遞到A組件,再由A組件篩選或者增長props,以後傳給B,這樣在B就能接收到最外層以及A傳遞來的props。一樣因爲A是中間層,A有權限控制B能獲得哪些props,也能額外增長一些屬性過去。

<B name={'zjj'}></B>
複製代碼
  • refs
// A/index

import React from 'react';
import './index.css';

export default (title = '我是標題') => {
  return (WrappedComponent) => {
    return class A extends React.Component {
      constructor (props) {
        super(props);
        this.state = {};
      }
      // [1] 定義一個點擊事件
      handleClick = () => {
        this.wref.getName();
      }


      render () {
        const prop = this.props;
        console.log(prop);
        return (
          <div className="a-container"> <div className="header"> <div className="title">{title}</div> <div className="close">X</div> </div> <div> <!-- 【2】綁定ref --> <WrappedComponent ref={ (v) => this.wref = v } sex={'男'} {...this.props} /> </div> <div> <!--【3】點擊事件觸發處--> <button onClick={this.handleClick}>獲取name</button> </div> </div> ) } } } } 複製代碼

咱們在B中定義一個getName方法。那麼經過點擊A中的按鈕,就能夠調用到

B/index

getName = () => {
  console.log('獲取到了name')
}
複製代碼
  • 抽取狀態
// A.js
import React from 'react';
import './index.css';

export default (title = '我是標題') => {
  return (WrappedComponent) => {
    return class A extends React.Component {
      constructor (props) {
        super(props);
        this.state = {
          value: ''
        };
      }

      // 點擊
      handleClick = () => {
        this.wref.getName();
      }

      // [1] 根據輸入設置 val
      handleOnInputChange = (e) => {
        this.setState({
          value: e.target.value
        })
      }

      render () {
        const prop = this.props;
        console.log(prop);
        
        // [2] 設置新的props
        var newProps = {
          value: this.state.value, // 傳入值
          onInput: this.handleOnInputChange // 監聽表單的輸入
        }
        return (
          <div className="a-container"> <div className="header"> <div className="title">{title}</div> <div className="close">X</div> </div> <div> <WrappedComponent ref={ (v) => this.wref = v } sex={'男'} {...this.props} {...newProps} /> // 【3】傳入子組件 </div> <div> <button onClick={this.handleClick}>獲取name</button> </div> </div> ) } } } } 複製代碼
// B/index.js
// 使用傳入的值,這樣即可以將子組件內部的實現抽取出來,放到公共的組件中去,統一管理
<input type="text" value={this.props.value} onInput={this.props.onInput} />
複製代碼
  • 包裝組件

其實咱們上面就是實現了包裹內部組件的效果。

相關文章
相關標籤/搜索