React 穿透獲取被高級組件裝飾的目標組件實例

image

圖片來源於互聯網es6

React 中常規的父子組件通訊都是經過 props 進行的,子組件經過 props 來接收父組件傳遞的狀態值以及方法,從而響應視圖的更新以及事件的執行。app

爲何要獲取組件實例

在不一樣的業務場景中也會存在很是規的通訊方式,例如須要在父組件中調用子組件屬性或者方法,這個時候就須要獲取子組件的實例來解決這個問題。函數

獲取組件實例的方法

首先須要說明的是,只有類組件纔有實例,函數式組件是沒有組件實例的。ui

React 官方提供了 3 中使用 ref 獲取實例的方式。this

  1. ref 接收一個字符串做爲參數 (不推薦)
class Index extends React.PureComponent {
    
        componentDidMount() {
            // 調用實例
            console.log(this.refs.classComponentInstance)
        }
        
        render() {
            return (
                <ClassComponent ref="classComponentInstance" /> ) } } 複製代碼
  1. ref 接收一個回調函數做爲參數
class Index extends React.PureComponent {
    
        componentDidMount() {
            // 調用實例
            console.log(this.classComponentInstance)
        }
        
        classComponentInstance = null
        
        render() {
            return (
                <ClassComponent ref={instance => {this.classComponentInstance=instance}} /> ) } } 複製代碼
  1. ref 接收 React.createRef 做爲參數
class Index extends React.PureComponent {
    
        componentDidMount() {
            // 調用實例
            console.log(this.classComponentInstance.current)
        }
        
        classComponentInstance = React.createRef()
        
        render() {
            return (
                <ClassComponent ref={this.classComponentInstance} /> ) } } 複製代碼

被高級組件裝飾的組件

所謂的高級組件也就一個函數,以組件做爲參數,以組件做爲返回值,主要是用於處理一些類似的邏輯,使組件可高度複用。spa

// Child.js
    
    @HocComponent
    export default class Child extends React.PureComponent {
        
        render(
            return (
                <div>this is Child</div>
            )
        )
    }
    
    
    // Parent.js
    
    import Child from './Child'
    
    class Parent extends React.PureComponent {
    
        childComponentInstance = null
        
        render(
            return (
                <Child ref={instance => {this.childComponentInstance=instance}} /> ) ) } 複製代碼

關於裝飾符可查看教程3d

上面示例中 Child 就是一個被高級組件使用裝飾符裝飾的類組件,當在 Parent 組件中調用並使用 ref 獲取其實例的時候就會發現 this.childComponentInstance 被賦值的實例並非 Child 的實例,而是 HocComponent 組件的實例。code

獲取被裝飾組件的實例

// Child.js
    
    @HocComponent
    export default class Child extends React.PureComponent {
    
        componentDidMount() {
            // 在 componentDidMount 週期中或者在 constructor 構造函數中執行父組件中傳遞過來的 getRef 方法,將實例 this 做爲參數
            this.props.getRef(this)
        }
        
        render(
            return (
                <div>this is Child</div>
            )
        )
    }
    
    
    // Parent.js
    
    import Child from './Child'
    
    class Parent extends React.PureComponent {
    
        childComponentInstance = null
        
        render(
            return (
                <Child getRef={instance => {this.childComponentInstance=instance}} /> ) ) } 複製代碼

經過上面的方式就能夠穿透高級組件,獲取到目標組件的實例component

抽象封裝爲可複用的高級組件

上面的方法雖然已經實現了咱們須要的功能,可是代碼侵入性太強,沒有複用度可言,因此咱們須要把這個功能提取出來。cdn

// util.js
    
    export const getRef = WrapperdComponent => {
        return props => {
            const { getRef, ...otherProps }  = props
            return <WrapperdComponent ref={getRef} {...otherProps} /> } } 複製代碼

當把穿透方法提取爲一個高級組件以後就能夠在任何須要的地方調用便可

// 使用示例
    // Child.js
    
    import { getRef } from './util'
    
    @HocComponent
    @getRef
    export default class Child extends React.PureComponent {
        
        render(
            return (
                <div>this is Child</div>
            )
        )
    }
    
    
    
    // Parent.js
    
    import Child from './Child'
    
    class Parent extends React.PureComponent {
    
        childComponentInstance = null
        
        render(
            return (
                <Child getRef={instance => {this.childComponentInstance=instance}} /> ) ) } 複製代碼

最後

文中若有錯誤,歡迎在評論區指正,謝謝閱讀

相關文章
相關標籤/搜索