日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

React?高階組件與Render?Props優缺點詳解_React

作者:何遇er ? 更新時間: 2022-12-12 編程語言

高階組件

高階組件(HOC)是一個接受組件作為參數并返回一個新組件的函數,如果多個組件有相同的邏輯,將這些邏輯用函數封裝,使它們能跨組件共用,這種用法稱為高階組件。下面的代碼演示什么是高階組件:

export default function WithPrintLog(InnerComponent) {
    return class extends React.Component{
        componentDidMount() {
            console.log('我被裝載了')
        }
        render() {
            return (<InnerComponent {...this.props}/>)
        }
    }
}

上述 WithPrintLog 是高階組件,它不改變 InnerComponent 在界面上的顯示,而是等 InnerComponent 裝載之后在控制臺打印'我被裝載了'。

總體而言,高階組件可以被分為兩大類。

  • 增強型:給組件增加額外的功能,比如前面舉例的 WithPrintLog。
  • 注入型:給組件注入額外的 props,比如 Redux 的 connect。

接下來,結合 TypeScript 分別介紹增強型和注入型高階組件。

增強型高級組件

增強型高階組件還是以 WithPrintLog 為例,只是在前面的基礎上增加 loading 效果,代碼如下:

interface Props {
    loading?: boolean
}
export default function WithPrintLog<P extends {}>(InnerComponent: React.ComponentType<P>) {
    return class extends React.Component<P & Props, never> {
        componentDidMount() {
            console.log('我被裝載了')
        }
        render() {
            const {loading, ...props} = this.props
            return (loading ? <div>loading...</div> : <InnerComponent {...(props as P)}/>)
        }
    }
}

React.ComponentType<P>React.ComponentClass<P> | React.FunctionComponent<P> 的別稱,因此 WithPrintLog 的參數只能是類組件或函數組件。分析上述代碼中的類型注解,類型參數 P 注解 InnerComponent 的 props。P & Props 注解返回值的 props,所以使用返回值時,除了傳 InnerComponent 所需的 props 還要傳 loading 字段。

注入型高階組件

注入型高階組件比增加強高階組件更常見,類型定義也更復雜,下面定義的 WithSubmitLog 便是一個注入型高階組件,代碼如下:

export interface InjectedProps {
    submitLog: (data: string) => void
}
export function WithSubmitLog<P extends InjectedProps>(InnerComponent: React.ComponentType<P>) {
    return class extends React.Component<Omit<P, keyof InjectedProps >, never> {
        submitLog = (data: string) => { /**todo*/ }
        render() {
            const props = ({
                ...this.props,
                submitLog: this.submitLog
            }) as P
            return <InnerComponent {...props}/>
        }
    }
}

<P extends InjectedProps>(InnerComponent: React.ComponentType<P>)使用了泛型約束,它約束類型參數P必須包含 InjectedProps 接口中的字段,所以InnerComponent 組件的 props 中必須存在 submitLog 字段。Omit<P, keyof InjectedProps>表示從類型P中剝除 InjectedProps 接口中的字段,所以使用 WithSubmitLog 返回的組件時,不必傳 submitLog 字段。

高階組件 VS Render Props

高階組件和 Render Props 都是提高代碼復用的有效手段,高階組件屬于靜態組合,Render Props 屬于動態組合。下面使用 Render Props 去改造上面的注入型高階組件 WithSubmitLog,代碼如下:

interface Props {
    render: (submitLog: (data: string) => void) => React.ReactNode;
}
class SubmitLogFromRender extends React.Component<Props , never> {
    submitLog = (data: string): void => { /**todo*/ }
    render(): React.ReactNode {
        return this.props.render(this.submitLog)
    }
}

與前面的 WithSubmitLog 相比,SubmitLogFromRender 簡單得多,一眼就能看出它能接受那些屬性,但是要明白高階組件返回的組件能接收哪些屬性就沒那么容易,另外由于 SubmitLogFromRender 組件的 render 屬性只是一個函數,所以它的值能來自第三方庫,CDN,甚至可以在程序運行時根據不同的情況動態加載不同的函數。

總結

高階組件能實現的效果 Render Props 都能實現,但反過來,Render Props 能實現的效果高階組件不一定能實現,這源于 Render Props 是動態組合,而高階組件是靜態組合。在日常開發中,我的最大感受是,分析高階組件能接受的屬性比分析運用 Render Props 技術組件的難度大得多。

原文鏈接:https://juejin.cn/post/7165661340453830670

欄目分類
最近更新