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