react 的高階元件再理解

Pandaaa發表於2019-02-26

今日貓片

image

優化一下 blog 介面,準備每次寫都給大家看一張貓片(大霧)。

寫在前面的話

  • 開始學習 react 的時候,有一個難點,高階元件。
  • 以前寫過一篇不太成熟的文章,這裡忙裡偷閒再來詳細的理解一下。
  • 最出名的高階元件就是 redux 狀態管理的 connect 元件。大家可以取看一看實現的原始碼。

高階函式的基本概念

想要理解高階元件,我們先來看看高階函式的含義。

  • 函式可以作為引數被傳遞
setTimeout(() => {
    console.log(1)
},1000)
複製程式碼
  • 函式可以作為返回值輸出
function foo(x){
    return function(){
        return x;
    }
}
複製程式碼
  • 類似於setTimeout(),setInterval()就是普通的高階函式。
setTimeout()
setInterval()

// ajax
$.get('/api/v1',function(){
    console.log('data')
})
複製程式碼

上面這兩個就是標準的高階函式

高階元件 high order component ,簡寫 HOC

-(原來以前的 HOC 就是高階元件)

高階元件理解和使用

  • 和高階函式一樣,需要函式去包裹一個元件,返回的是一個元件而已
// A.js
import React, { Component } from 'react';
function A(WrapperedComponent){
    return class test extends Component{
        return <div>
            <WrapperedComponent />
        </div>
    }
}

export default A;

// 其他元件使用的時候
// B.js
import A from './A';

class B extends Component{
    return <div>
        hello world!!
    </div>
}
export default A(B)
複製程式碼

高階元件的使用

  • 直接包裹 HOC(WrapperedComponent)
  • 使用裝飾器 @HOC
    • 要 nom run eject(這裡就不詳細寫了)
    • 安裝 babel 適配檔案等

編寫高階元件

  • 實現一個普通元件
  • 函式包裹這個元件

一個簡單的高階元件 demo

-- index.ts
-- /src
---- HOCprogress.tsx
---- A.tsx
---- B.tsx
---- C.tsx

複製程式碼

HOCprogress.tsx(1)

import React, { Component } from "react";

// 然後包裹一個 function,用WrapperedComponent傳入 class 的 render()中。

function HOCprogress(WrapperedComponent, value: number) {

//先寫 class 
  return class hocForm extends Component {
    render() {
      return (
        <div>
          <WrapperedComponent />
        </div>
      );
    }
  };
}

export default HOCprogress;

複製程式碼
  • 優化一下,新增簡單的進度條
// HOCprogress.tsx
import React, { Component } from "react";

function HOCprogress(WrapperedComponent, value: number) {
  return class hocForm extends Component {
    render() {
    
      // 新增樣式 
      const innerStyle = {
        padding:'10px',
        width: "100%"
      };
      const percentStyle = {
        width: `${value}%`,
        height: "20px",
        background:
          "url(https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2440333743,1684406640&fm=26&gp=0.jpg)"
      };

      return (
          <div style={innerStyle}>
            <div style={percentStyle}> {value} %</div>
            <WrapperedComponent />
          </div>
      );
    }
  };
}

export default HOCprogress;
複製程式碼
  • 新增 A,B,C三個檔案

A.tsx

import React, { Component } from "react";
// 引入高階函式
import HOCprogress from "./HOCprogress.tsx";

class A extends Component {
  render() {
    return <div>這是 A 元件!</div>;
  }
}
// 使用高階元件包裹 A 元件
export default HOCprogress(A, 56);

複製程式碼

B.tsx

import React, { Component } from "react";
import HOCprogress from "./HOCprogress.tsx";


class B extends Component {
  render() {
    return <div>這是 B 元件!</div>;
  }
}

// 我們可以使用 @HOCprogress 裝飾器這樣的方式來替代函式包裹這種方式具體的見我的裝飾器的那篇文章。
export default HOCprogress(B, 98);

// C.tsx 同上
複製程式碼

index.ts

import React from "react";
import C from "./C.tsx";
import B from "./B.tsx";
import A from "./A.tsx";

class App extends React.Component {
    render(){
        <div>
            <A />
            <B />
            <C />
        </div>
    }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
複製程式碼

最後來看看效果

image

寫在最後

  • 當然高階元件有非常多的用法還可以去了解和學習,這裡只是粗淺的入門瞭解。
  • 可以在代理模式中,去
    • 操作 props
    • 抽取元件狀態
    • 訪問 ref
    • 包裝元件

參考

相關文章