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