【原創(chuàng)】react-源碼解析 - Component&Ref(3)

一、Component&PureComponent

?看到這個(gè)api想必大家再熟悉不過(guò)了,平常我們?cè)趓eact開(kāi)發(fā)過(guò)程中寫(xiě)的組件都是繼承自這個(gè)Component組件,比如我們?cè)诼暶鰿lassComponent的時(shí)候extends的就是React.Component,在看源碼只是我個(gè)人覺(jué)得寫(xiě)個(gè)class應(yīng)該實(shí)現(xiàn)了很多復(fù)雜的功能比如說(shuō)setState和render方法等,但是看了源碼之后顛覆了我之前的認(rèn)知:Component

Component(props, context, updater)

在源碼中Component方法只是簡(jiǎn)單的對(duì)props和context進(jìn)行了賦值操作,這兩個(gè)傳入的參數(shù)我們都很熟悉,最后這個(gè)updater參數(shù)我們我們接觸到。通過(guò)源碼我們看到在Component的原型上聲明了setState方法:

// 原型上聲明setState方法==接受兩個(gè)參數(shù)partialState待更新的state,callback回調(diào)函數(shù)Component.prototype.setState = function(partialState, callback) { ?

????invariant(// 判斷傳入?yún)?shù)是否合法--包括state和callBack

?????????typeof partialState ==='object'||typeof partialState ==='function'||partialState == null,

????????'setState(...): takes an object of state variables to update or a'+'function which returns an ????????object of state variables.', );

????????// setStated的時(shí)候在component ?

????????// 里面沒(méi)有任何操作只是調(diào)用了初始化傳入的this.updater里面的enqueueSetState方法?

????????// 將this,state,callBack,和一個(gè)字符串‘setState’傳入==>個(gè)人認(rèn)為這個(gè)setState為一個(gè)type

?????????// enqueueSetState todo?此方法在react-dom中實(shí)現(xiàn)=后續(xù)

?????????this.updater.enqueueSetState(this, partialState, callback,'setState');

};

該函數(shù)內(nèi)部只是判斷了傳入?yún)?shù)的合法性最后調(diào)用了Component中updater方法上的enqueueSetState。然后方法結(jié)束,這里去查了一下資料,這個(gè)方法具體的實(shí)現(xiàn)是在react-dom中完成的。為什么要這樣做呢,因?yàn)樵趓eact中只是簡(jiǎn)單的提供了這個(gè)方法的入口,具體的調(diào)用需要看你在哪個(gè)平臺(tái)下使用,比如在react-dom中和在react-native中的調(diào)用肯定是不同的。在原型上也聲明了:

// forceUpdate-強(qiáng)制更新組件State方法

Component.prototype.forceUpdate = function(callback) { this.updater.enqueueForceUpdate(this, callback,'forceUpdate');};

看到這里我們發(fā)現(xiàn)只是調(diào)用了updater 的enqueueForceUpdate方法,個(gè)人認(rèn)為跟字面意思一樣,對(duì)state的進(jìn)行了強(qiáng)制更新操作。PureComponent的用法我們不必再去贅述,該方法實(shí)際就是對(duì)Component方法進(jìn)行了繼承,但是多加了一個(gè)屬性:

// 在原型上添加一個(gè)額外的isPureReactComponent屬性/,標(biāo)識(shí)是一個(gè)pureComponent

Object.assign(pureComponentPrototype, Component.prototype);pureComponentPrototype.isPureReactComponent =true;

isPureReactComponent用來(lái)說(shuō)明是一個(gè)PureComponent。最后將這兩個(gè)方法導(dǎo)出,到這里我們有關(guān)Componet的源碼已經(jīng)完結(jié)了,我們看到在react中其實(shí)沒(méi)有太多復(fù)雜的操作,只是對(duì)傳入?yún)?shù)的賦值,已經(jīng)留下了一些函數(shù)入口。像更新渲染等操作實(shí)際都放在了react-dom中去完成。

二、createRef&ref

????????在開(kāi)發(fā)中我們通常會(huì)有這樣的需求,有時(shí)候我們需要獲取某個(gè)Dom節(jié)點(diǎn)或者拿到classComponent類(lèi)型的子組件的實(shí)例,進(jìn)而操作這個(gè)子組件。比如說(shuō)我們需要通過(guò)在父級(jí)組件中調(diào)用到子組件中的方法,從而更新子組件,這里的更新就不僅僅局限于更新props,通常我們跟新props也不需要獲得子組件的實(shí)例。 這里通過(guò)ref這個(gè)屬性會(huì)讓我們很容易操作子組件。

一般在現(xiàn)有版本中有三種使用ref的方法:

(1)string 類(lèi)型ref ref="string" == {不推薦,下個(gè)大版本會(huì)廢棄}

(2)function類(lèi)型 ref = {ele => (this.childRef = ele )}

(3)React.createRef()

大致用法類(lèi)似于這個(gè)樣子,需要注意的是我們?cè)谑褂胷ef時(shí)候,如果目標(biāo)組件是一個(gè)function類(lèi)型的Component一般來(lái)說(shuō)這個(gè)時(shí)候拿到的ref肯定是undefined,因?yàn)閒unctionComponent是沒(méi)有實(shí)例的,后面我們會(huì)介紹一個(gè)叫做forward-ref的屬性,這個(gè)屬性可以讓我們?nèi)〉胶瘮?shù)類(lèi)型組件上去使用ref。接下來(lái)我們?nèi)タ纯碿reateRef方法的源碼:createRef

????????這里的源碼很簡(jiǎn)單只是創(chuàng)建了一個(gè)refObject在上面聲明了一個(gè)為null的currenrt屬性。然后將這個(gè)對(duì)象返回。其實(shí)這個(gè)源碼看到這里也看不出ref到底是怎么掛載在組件的this上面的。這里應(yīng)該是在react更新的過(guò)程中實(shí)現(xiàn)的,react中只有更新到結(jié)束一個(gè)完整的流程,至于到底是怎么掛載的ref我們接著往下讀。

了解更多:react-source-code

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容