摘要:創建一個普通函數因為的存在所以變成構造函數創建一個方法在方法中,創建一個中間實例對中間實例經過邏輯處理之后返回使用方法創建實例而恰好,高階組件的創建邏輯與使用,與這里的方法完全一致。因為方法其實就是構造函數的高階組件。
很多人寫文章喜歡把問題復雜化,因此當我學習高階組件的時候,查閱到的很多文章都給人一種高階組件高深莫測的感覺。但是事實上卻未必。
有一個詞叫做“封裝”。相信寫代碼這么久了,大家對這個詞所表達的含義都不會陌生。我們通常會將功能相同或者相似的代碼提取出來封裝成為一個可共用的函數或者對象,這也是我們從初學者慢慢進階的必經之路。而高階組件就是一個封裝行為。
但是高階組件的封裝與我們通常所使用的不太一樣,如果完全一樣也就不是那么難理解了。好在我們有一個常用的口頭語“包一層“剛好可以用來簡單解釋高階組件的不同。在普通組件外面包一層邏輯,就是高階組件。
關于”包一層“,可以通過一個非常簡單的例子來理解。
import React, { Component } from "react"; class Div extends Component { componentDidMount() { console.log("這是新增的能力"); } render () { return ({ this.props.children }) } } export default Div;
在上面的例子中,我們把html的DIV標簽作為基礎元件。對他新增了一個輸出一條提示信息的能力。而新的Div組件,就可以理解為div標簽的高階組件。到這里希望大家已經理解了包一層的具體含義。
為了更加透徹的理解“包一層”的概念,我們需要來回顧一下new與構造函數之間的關系。在前面我有文章提到過為什么構造函數中this在運行時會指向new出來的實例,不知道還有沒有人記得。我將那段代碼復制過來。
// 先一本正經的創建一個構造函數,其實該函數與普通函數并無區別 var Person = function(name, age) { this.name = name; this.age = age; this.getName = function() { return this.name; } } // 將構造函數以參數形式傳入 function New(func) { // 聲明一個中間對象,該對象為最終返回的實例 var res = {}; if (func.prototype !== null) { // 將實例的原型指向構造函數的原型 res.__proto__ = func.prototype; } // ret為構造函數執行的結果,這里通過apply,將構造函數內部的this指向修改為指向res,即為實例對象 var ret = func.apply(res, Array.prototype.slice.call(arguments, 1)); // 當我們在構造函數中明確指定了返回對象時,那么new的執行結果就是該返回對象 if ((typeof ret === "object" || typeof ret === "function") && ret !== null) { return ret; } // 如果沒有明確指定返回對象,則默認返回res,這個res就是實例對象 return res; } // 通過new聲明創建實例,這里的p1,實際接收的正是new中返回的res var p1 = New(Person, "tom", 20); console.log(p1.getName()); // 當然,這里也可以判斷出實例的類型了 console.log(p1 instanceof Person); // true
在上面的例子中,首先我們定義了一個本質上與普通函數沒區別的構造函數,然后將該構造函數作為參數傳入New函數中。我在New函數中進行了一些的邏輯處理,讓New函數的返回值為一個實例,正因為New的內部邏輯,讓構造函數中的this能夠指向返回的實例。這個例子就是一個“包一層”的案例。如果因為基礎不夠扎實導致你對上面的例子確實理解不了,我們還可以簡單粗暴的把上面的例子分成三個步驟來記憶。
創建一個普通函數(因為new的存在所以變成構造函數)
創建一個new方法
在new方法中,創建一個中間實例res
對中間實例res經過邏輯處理之后返回res
使用new方法創建實例
而恰好,高階組件的創建邏輯與使用,與這里的new方法完全一致。因為new方法其實就是構造函數的”高階組件“。按照這個步驟,我們來嘗試一步一步創建一個高階組件。
第一步,創建一個最簡單的基礎組件。
class Basic extends Component { render() { return ({ this.props.children }) } }
第二步,根據上栗new方法的步驟,來創建高階組件。
// src/Addsss.jsx import React from "react"; // 基礎組件作為高階組件的參數傳入 function Addsss(Container) { // 創建一個中間組件,該中間組件會在添加了邏輯之后返回 return class Asss extends React.Component { componentDidMount() {} render() { return ( // 高階組件往基礎組件中傳入了一個name屬性,這是高階組件賦予基礎組件的新能力,當然,根據實際需求還可以添加更為復雜的新能力{ this.props.children } ) } } } export default Addsss;
高階組件在基礎組件中調用,并將高階組件的運行結果返回給模塊外部。因此基礎組件的代碼調整如下:
// src/basic.jsx import React, { Component } from "react"; import Addsss from "./Addsss"; class Basic extends Component { componentDidMount() { // 在基礎組件中試圖訪問高階組件傳入的新參數 console.log(this.props.name); } render() { return ({ this.props.children }) } } // 這里相當于執行了一次new操作,返回了一個實例,其實運行結果真是高階組件中的中間組件 export default Addsss(Basic);
我們看到其實在基礎組件中,對外拋出的接口是Addsss(Basic),這是高階組件里定義的函數運行的結果。也就是說,其實基礎組件中返回的是高階組件中定義的Asss中間組件。這和new的思路幾乎完全一致。
所以我們可以簡單理解為:react組件的高階組件,就是在基礎react組件外面包一層,給該基礎組件賦予新的能力。
當然,想要熟練使用高階組件并不是一件容易的事情,我們還需要更多的思考他。在下面一篇文章中我將會以實際的案例來分析高階組件的使用場景與他到底給我們帶來了哪些便利。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/83689.html
摘要:前面有講到過很多頁面會在初始時驗證登錄狀態與用戶角色。這個時候就涉及到一個高階組件的嵌套使用。而每一個高階組件函數執行之后中所返回的組件,剛好可以作為下一個高階組件的參數繼續執行,而并不會影響基礎組件中所獲得的新能力。 前面有講到過很多頁面會在初始時驗證登錄狀態與用戶角色。我們可以使用高階組件來封裝這部分驗證邏輯。封裝好之后我們在使用的時候就可以如下: export default w...
摘要:在前端基礎進階八深入詳解函數的柯里化一文中,我有分享柯里化相關的知識。雖然說高階組件與柯里化都屬于比較難以理解的知識點,但是他們組合在一起使用時并沒有新增更多的難點。 可能看過我以前文章的同學應該會猜得到當我用New的方法來舉例學習高階組件時,接下來要分享的就是柯里化了。高階組件與函數柯里化的運用是非常能夠提高代碼逼格的技巧,如果你有剩余的精力,完全可以花點時間學習一下。 在前端基礎進...
摘要:高階組件可以封裝公共邏輯,給當前組件傳遞方法屬性,添加生命周期鉤子等。二是基礎組件的靜態方法也會因為高階組件的包裹會丟失。如果在開發中確實遇到了必須使用它們,就一定要注意高階組件的這個問題并認真解決。 高階組件可以封裝公共邏輯,給當前組件傳遞方法屬性,添加生命周期鉤子等。 案例: 一個項目中有的頁面需要判斷所處環境,如果在移動端則正常顯示頁面,并向用戶提示當前頁面所處的移動端環境,如果...
摘要:課程制作和案例制作都經過精心編排。對于開發者意義重大,希望對有需要的開發者有所幫助。是從提案轉為正式加入的新特性。并不需要用繼承,而是推薦用嵌套。大型項目中模塊化與功能解耦困難。從而更加易于復用和獨立測試。但使用會減少這種幾率。 showImg(https://segmentfault.com/img/bVbpNRZ?w=1920&h=1080); 講師簡介 曾任職中軟軍隊事業部,參與...
閱讀 473·2021-10-09 09:57
閱讀 477·2019-08-29 18:39
閱讀 817·2019-08-29 12:27
閱讀 3032·2019-08-26 11:38
閱讀 2672·2019-08-26 11:37
閱讀 1298·2019-08-26 10:59
閱讀 1385·2019-08-26 10:58
閱讀 995·2019-08-26 10:48