成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

深入React知識(shí)點(diǎn)整理(一)

Gilbertat / 2889人閱讀

摘要:以我自己的理解,函數(shù)式編程就是以函數(shù)為中心,將大段過程拆成一個(gè)個(gè)函數(shù),組合嵌套使用。越來越多的跡象表明,函數(shù)式編程已經(jīng)不再是學(xué)術(shù)界的最愛,開始大踏步地在業(yè)界投入實(shí)用。也許繼面向?qū)ο缶幊讨?,函?shù)式編程會(huì)成為下一個(gè)編程的主流范式。

使用React也滿一年了,從剛剛會(huì)使用到逐漸探究其底層實(shí)現(xiàn),以便學(xué)習(xí)幾招奇技淫巧從而在自己的代碼中使用,寫出高效的代碼。下面整理一些知識(shí)點(diǎn),算是React看書,使用,感悟的一些總結(jié):

函數(shù)式編程

React事件系統(tǒng)

高階組件

組件性能優(yōu)化

React源碼初探

VirtualDOM 模型

1. 函數(shù)式編程

函數(shù)式編程是一種如何編寫程序的方法論,與之對(duì)應(yīng)的就是命令式編程。

以我自己的理解,函數(shù)式編程就是以函數(shù)為中心,將大段過程拆成一個(gè)個(gè)函數(shù),組合嵌套使用。這個(gè)思想在JavaScript中很常見。舉個(gè)阮一峰老師的例子:

我們有一個(gè)數(shù)學(xué)表達(dá)式:

(1 + 2) * 3 - 4

將上述表達(dá)式不假思索的轉(zhuǎn)換成代碼:

const a = 1 + 2;
const b = a * 3;
const c = b - 4;

以函數(shù)式編程思想:將運(yùn)算過程定義成不同的函數(shù),如下:

const result = substract(multiply(add(1, 2), 3), 4);

是不是感覺很高端但又一臉懵逼。沒錯(cuò),函數(shù)式編程在處理大段過程中就顯得很容易理解,但是簡(jiǎn)單邏輯中就顯得復(fù)雜,因?yàn)榉庋b起來的函數(shù)需要時(shí)間去閱讀。

對(duì)上述表達(dá)式進(jìn)行變形:

 add(1,2).multiply(3).subtract(4);

是不是也很熟悉。函數(shù)式編程在JavaScript中應(yīng)用確實(shí)很普遍。

目前最當(dāng)紅的Python、Ruby、Javascript,對(duì)函數(shù)式編程的支持都很強(qiáng),就連老牌的面向?qū)ο蟮腏ava、面向過程的PHP,都忙不迭地加入對(duì)匿名函數(shù)的支持。越來越多的跡象表明,函數(shù)式編程已經(jīng)不再是學(xué)術(shù)界的最愛,開始大踏步地在業(yè)界投入實(shí)用。

也許繼"面向?qū)ο缶幊?之后,"函數(shù)式編程"會(huì)成為下一個(gè)編程的主流范式(paradigm)。未來的程序員恐怕或多或少都必須懂一點(diǎn)。

這里不做多介紹,有興趣可以看看:

函數(shù)式編程初探

什么是函數(shù)式編程思維?

函數(shù)式編程

2.React事件系統(tǒng) React事件與DOM事件
React 基于 Virtual DOM 實(shí)現(xiàn)了一個(gè) SyntheticEvent (合成事件)層,我們所定義的事件處理器會(huì)接收到一個(gè) SyntheticEvent 對(duì)象的實(shí)例,它完全符合 W3C 標(biāo)準(zhǔn),不會(huì)存在任何 IE 標(biāo)準(zhǔn)的兼容性問題。并且與原生的瀏覽器事件一樣擁有同樣的接口,同樣支持事件的冒泡機(jī)制,我們可以使用 stopPropagation() 和 preventDefault() 來中斷它。

所有事件都自動(dòng)綁定到最外層上。如果需要訪問原生事件對(duì)象,可以使用 nativeEvent 屬性。

使用React的時(shí)候都知道,React有一套自己的事件系統(tǒng),典型的特征就是元素綁定事件都要使用React提供的事件接口:

// in html


// in React

React的合成事件實(shí)際上是做了一層事件委托(事件代理):

它并不會(huì)把事件處理函數(shù)直接綁定到真實(shí)的節(jié)點(diǎn)上,而是把所有事件綁定到結(jié)構(gòu)的最外層,使用一個(gè)統(tǒng)一的事件監(jiān)聽器,這個(gè)事件監(jiān)聽器上維持了一個(gè)映射來保存所有組件內(nèi)部的事件監(jiān)聽和處理函數(shù)。當(dāng)組件掛載或卸載時(shí),只是在這個(gè)統(tǒng)一的事件監(jiān)聽器上插入或刪除一些對(duì)象;當(dāng)事件發(fā)生時(shí),首先被這個(gè)統(tǒng)一的事件監(jiān)聽器處理,然后在映射里找到真正的事件處理函數(shù)并調(diào)用。這樣做簡(jiǎn)化了事件處理和回收機(jī)制,效率
也有很大提升。

也就是說React使用了一個(gè)事件代理,所有事件綁定都只是事件代理保存了一個(gè)映射,事件發(fā)生的時(shí)候,調(diào)用處理函數(shù),并沒有真正的使用原生事件。我們來看一個(gè)例子:

componentDidMount () {
    document.querySelector("#testEvent").addEventListener("click", (e)=>{
        console.log("dom event");
        console.log(e);
    })
}
componentDidUnMount () {
    document.querySelector("#testEvent").removeEventListener("click");
}
handleClick (e) {
    console.log("react event");
    console.log(e);
}
render () {
    return (
        
Test React Event
Test dom Event
); }

這里有兩個(gè)div,使用React綁定事件和原生DOM事件,兩種事件綁定方法不同導(dǎo)致相同的效果,完全不同的原理。

使用原生DOM綁定打印的事件就是原生的,React事件打印出來的事件:

可以看到是個(gè)Proxy對(duì)象,里面有觸發(fā)事件的target和處理事件的handler,這就是React的合成事件。

另外如果在react中綁定原生事件,組件卸載的時(shí)候記得解除綁定,避免內(nèi)存泄漏。

React的合成事件還有一個(gè)優(yōu)點(diǎn)在于不需要處理瀏覽器事件兼容性,方便操作。

原生事件分成三個(gè)部分:事件捕獲,目標(biāo)事件處理,事件冒泡。IE9以下不支持事件捕獲,所以React沒有實(shí)現(xiàn)它,僅支持事件冒泡。

有些事件React沒有實(shí)現(xiàn),window.resize事件。

所以,請(qǐng)盡量避免在 React 中混用合成事件和原生 DOM 事件。因?yàn)閮烧呤遣煌氖录到y(tǒng),阻止 React 事件冒泡的行為只能用于 React 合成事件系統(tǒng)中,且沒辦法阻止原生事件的冒泡。反之,在原生事件中的阻止冒泡行為,卻可以阻止 React 合成事件的傳播。

3.高階組件

高階組件是React中比較有特點(diǎn)的一類問題,高階組件(High Order Component)文章里多帶帶進(jìn)行了詳細(xì)介紹。

這里只是補(bǔ)一張圖:組合式組件開發(fā)實(shí)踐

4.組件性能優(yōu)化
從過往的經(jīng)驗(yàn)與實(shí)踐中,我們都知道影響網(wǎng)頁(yè)性能最大的因素是瀏覽器的重繪(reflow)和重排版(repaint)。React 背后的 Virtual DOM 就是盡可能地減少瀏覽器的重繪與重排版。

關(guān)于瀏覽器重繪和重排版問題,請(qǐng)看我之前的文章:瀏覽器渲染頁(yè)面過程與頁(yè)面優(yōu)化

這里要介紹的就是:

多使用純函數(shù):無依賴;相同輸入相同輸出;重復(fù)使用。

PureComponent:本質(zhì)上講,PureComponent就是重寫了shouldComponentUpdate,對(duì)nextPropsnextState與當(dāng)前state和props做淺比較,性能上優(yōu)化。

Immutable:使用Immutable共享數(shù)據(jù)節(jié)點(diǎn),節(jié)省渲染。

key:列表渲染指定key,相同key不渲染;盡量不要使用index當(dāng)key,最好是id。

react-addons-pref:插件量化性能優(yōu)化效果。

對(duì)這塊有興趣的,推薦幾篇文章:

React組件性能調(diào)優(yōu)

React性能優(yōu)化總結(jié)

高性能 React 組件

5.React源碼初探

React項(xiàng)目目錄構(gòu)成如下圖:

addons:工具方法插件:PureRenderMixinCSSTransitionGrouo、Fragment、LinkedStateMixin

isomorphic:包含一系列同構(gòu)方法。

shared:公用方法和常用方法。

test:測(cè)試方法。

core/tests:邊界錯(cuò)誤的測(cè)試用例。

renderers:React的核心代碼,包含大部分功能實(shí)現(xiàn),因此進(jìn)行多帶帶分析。

renderers包包含內(nèi)容:

dom:包含client,server和shared。

client:包含DOM操作方法(findDOMNode,setInnerHTML,setTextContent等)以及事件方法。這里的事件方法主要是一些非底層的實(shí)用性事件方法,
如事件監(jiān)聽(ReactEventListener)、常用事件方法(TapEventPlugin、EnterLeaveEventPlugin)以及一些合成事件(SyntheticEvents
等)。

server:主要包含服務(wù)端渲染的實(shí)現(xiàn)和方法(如 ReactServerRendering、ReactServerRenderingTransaction
等)。

shared:包含文本組件(ReactDOMTextComponent)、標(biāo)簽組件(ReactDOMComponent)、
DOM 屬性操作(DOMProperty、DOMPropertyOperations)、CSS 屬性操作(CSSProperty、
CSSPropertyOperations)等。

shared:包含event和reconciler。

event:包含一些更為底層的事件方法,如事件插件中心(EventPluginHub)、事件注冊(cè)
(EventPluginRegistry)、事件傳播(EventPropagators)以及一些事件通用方法。
React 自定義了一套通用事件的插件系統(tǒng),該系統(tǒng)包含事件監(jiān)聽器、事件發(fā)射器、事
件插件中心、點(diǎn)擊事件、進(jìn)/出事件、簡(jiǎn)單事件、合成事件以及一些事件方法。

reconciler:稱為協(xié)調(diào)器,它是最為核心的部分,包含 React 中自定義組件的實(shí)現(xiàn)
(ReactCompositeComponent)、組件生命周期機(jī)制、setState 機(jī)制(ReactUpdates、
ReactUpdateQueue)、DOM diff 算法(ReactMultiChild)等重要的特性方法。

這里簡(jiǎn)單介紹React目錄構(gòu)成以及每塊的功能,大致了解,需要的時(shí)候找到對(duì)應(yīng)位置深入研究。

React 也能夠?qū)崿F(xiàn) Virtual DOM 的批處理更新,當(dāng)操作 Virtual DOM 時(shí), 不會(huì)馬上生成真實(shí)的DOM,而是會(huì)將一個(gè)事件循環(huán)(event loop)內(nèi)的兩次數(shù)據(jù)更新進(jìn)行合并,這樣就使得 React 能夠在事件循環(huán)的結(jié)束之前完全不用操作真實(shí)的 DOM。
6.VirtualDOM 模型

VirtualDOM是React的一個(gè)核心,也是React一個(gè)著名的特點(diǎn),之前我有篇文章對(duì)此有過簡(jiǎn)單的介紹,以及如何簡(jiǎn)單實(shí)現(xiàn)根據(jù)VirtualDOM渲染頁(yè)面:React學(xué)習(xí)報(bào)告,可以做基本入門查看。

VirtualDOM與真實(shí)DOM的關(guān)系很簡(jiǎn)單:

真實(shí)DOM可以理解為是xml格式存儲(chǔ)DOM,VirtualDOM可以理解為json格式的存儲(chǔ)DOM。

只需要存儲(chǔ)節(jié)點(diǎn)的關(guān)鍵信息:類型,id,class,屬性,style,事件,嵌套關(guān)系等即可,按照一定的轉(zhuǎn)換規(guī)則將json轉(zhuǎn)成DOM。

流程關(guān)系:jsx語(yǔ)法->識(shí)別jsx語(yǔ)法生成VirtualDOM樹->根據(jù)渲染規(guī)則生成真實(shí)DOM->HTML。

Virtual DOM中的節(jié)點(diǎn)成為ReactNode,分成ReactELement,ReactFragment,ReactText。ReactElement又分成ReactComponentElemnt和ReactDOMElement。

下面是 ReactNode 中不同類型節(jié)點(diǎn)所需要的基礎(chǔ)元素:

type ReactNode = ReactElement | ReactFragment | ReactText;
type ReactElement = ReactComponentElement | ReactDOMElement;
type ReactDOMElement = {
 type : string,
 props : {
 children : ReactNodeList,
 className : string,
 etc.
 },
 key : string | boolean | number | null,
 ref : string | null
};
type ReactComponentElement = {
 type : ReactClass,
 props : TProps,
 key : string | boolean | number | null,
 ref : string | null
};
type ReactFragment = Array;
type ReactNodeList = ReactNode | ReactEmpty;
type ReactText = string | number;
type ReactEmpty = null | undefined | boolean; 

這里以DOM標(biāo)簽(ReactDOMComponent)為例,介紹VirtualDOM模型如何創(chuàng)建節(jié)點(diǎn):

屬性更新
當(dāng)執(zhí)行 mountComponent 方法時(shí),ReactDOMComponent 首先會(huì)生成標(biāo)記和標(biāo)簽,通過 this.createOpenTagMarkupAndPutListeners(transaction) 來處理 DOM 節(jié)點(diǎn)的屬性和事件。

如果節(jié)點(diǎn)綁定了事件,則針對(duì)當(dāng)前的節(jié)點(diǎn)添加代理,調(diào)用enqueuePutListener(this,propKey, propValue, transaction)。

存在樣式的話,樣式合并Object.assign({}, props.style),然后通過CSSPropertyOperations.createMarkupForStyles(propValue, this)創(chuàng)建樣式。

通過DOMPropertyOperations.createMarkupForProperty(propKey, propValue)創(chuàng)建屬性。

通過DOMPropertyOperations.createMarkupForID(this._domID)創(chuàng)建唯一標(biāo)識(shí)。

其實(shí),早有開發(fā)者向 React 官方提過問題,建議去掉這個(gè)雞肋的屬性標(biāo)識(shí)(data-reactid)這終于在 React 15.0版本上實(shí)現(xiàn)了。據(jù)官方宣稱,去除 data-reactid 使得 React 性能有了 10% 的提升。
更新子節(jié)點(diǎn)
當(dāng)執(zhí)行 mountComponent 方法時(shí),ReactDOMComponent 會(huì)通過 this._createContentMarkup(transaction, props, context) 來處理 DOM 節(jié)點(diǎn)的內(nèi)容。

先是刪除不需要的子節(jié)點(diǎn)和內(nèi)容。如果舊節(jié)點(diǎn)存在,而新節(jié)點(diǎn)不存在,說明當(dāng)前節(jié)點(diǎn)在更新后被刪除,此時(shí)執(zhí)行方法 this.updateChildren(null, transaction, context);如果舊的內(nèi)容存在,而新的內(nèi)容不存在,說明當(dāng)前內(nèi)容在更新后被刪除,此時(shí)執(zhí)行方法 this.updateTextContent("")。

再是更新子節(jié)點(diǎn)和內(nèi)容。如果新子節(jié)點(diǎn)存在,則更新其子節(jié)點(diǎn),此時(shí)執(zhí)行方法 this.updateChildren(nextChildren,transaction, context);如果新的內(nèi)容存在,則更新內(nèi)容,此時(shí)執(zhí)行方法 this.updateTextContent("" + nextContent)。

當(dāng)卸載組件時(shí),ReactDOMComponent 會(huì)進(jìn)行一系列的操作,如卸載子節(jié)點(diǎn)、清除事件監(jiān)聽、清空標(biāo)識(shí)等。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92140.html

相關(guān)文章

  • 深入React識(shí)點(diǎn)整理(二)

    摘要:承接上文,深入知識(shí)點(diǎn)整理一使用也滿一年了,從剛剛會(huì)使用到逐漸探究其底層實(shí)現(xiàn),以便學(xué)習(xí)幾招奇技淫巧從而在自己的代碼中使用,寫出高效的代碼。有限狀態(tài)機(jī),表示有限個(gè)狀態(tài)以及在這些狀態(tài)之間的轉(zhuǎn)移和動(dòng)作等行為的模型。 承接上文,深入React知識(shí)點(diǎn)整理(一)使用React也滿一年了,從剛剛會(huì)使用到逐漸探究其底層實(shí)現(xiàn),以便學(xué)習(xí)幾招奇技淫巧從而在自己的代碼中使用,寫出高效的代碼。下面整理一些知識(shí)點(diǎn),...

    villainhr 評(píng)論0 收藏0
  • Record 前端開發(fā)知識(shí)整理分享

    showImg(https://segmentfault.com/img/remote/1460000018716142?w=200&h=200); showImg(https://segmentfault.com/img/remote/1460000018716143);showImg(https://segmentfault.com/img/remote/1460000010953710);...

    TZLLOG 評(píng)論0 收藏0
  • 本關(guān)于 React.js 的小書

    摘要:因?yàn)楣ぷ髦幸恢痹谑褂?,也一直以來想總結(jié)一下自己關(guān)于的一些知識(shí)經(jīng)驗(yàn)。于是把一些想法慢慢整理書寫下來,做成一本開源免費(fèi)專業(yè)簡(jiǎn)單的入門級(jí)別的小書,提供給社區(qū)。本書的后續(xù)可能會(huì)做成視頻版本,敬請(qǐng)期待。本作品采用署名禁止演繹國(guó)際許可協(xié)議進(jìn)行許可 React.js 小書 本文作者:胡子大哈本文原文:React.js 小書 轉(zhuǎn)載請(qǐng)注明出處,保留原文鏈接以及作者信息 在線閱讀:http://huzi...

    Scorpion 評(píng)論0 收藏0
  • 深入理解js

    摘要:詳解十大常用設(shè)計(jì)模式力薦深度好文深入理解大設(shè)計(jì)模式收集各種疑難雜癥的問題集錦關(guān)于,工作和學(xué)習(xí)過程中遇到過許多問題,也解答過許多別人的問題。介紹了的內(nèi)存管理。 延遲加載 (Lazyload) 三種實(shí)現(xiàn)方式 延遲加載也稱為惰性加載,即在長(zhǎng)網(wǎng)頁(yè)中延遲加載圖像。用戶滾動(dòng)到它們之前,視口外的圖像不會(huì)加載。本文詳細(xì)介紹了三種延遲加載的實(shí)現(xiàn)方式。 詳解 Javascript十大常用設(shè)計(jì)模式 力薦~ ...

    caikeal 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<