摘要:對回收的處理在中,回收調(diào)用了兩個方法,節(jié)點的回收一般會調(diào)用,組件的回收會調(diào)用。個人理解從以上源碼閱讀中我們可以看到,最大的性能問題在于遞歸的,中的與也是為了緩解這個問題。為不同類型的更新分配優(yōu)先級。
對回收的處理
在preact中,回收調(diào)用了兩個方法,dom節(jié)點的回收一般會調(diào)用recollectNodeTree,組件的回收會調(diào)用unmountComponent。
preact復(fù)用dom的秘密在于當要卸載一個組件的時候,只有組件的根節(jié)點會從父節(jié)點上卸載掉,組件完整的dom仍然存在,被卸載的組件會保存在components對象中。
在創(chuàng)建組件的時候又通過nodeName拿到對應(yīng)的dom節(jié)點樹,掛載在組件實例的inst.nextBase上,在renderComponent的時候,再diff nextBase與新的虛擬dom樹rendered。
相關(guān)主要代碼如下:
function createComponent(Ctor, props, context) { let list = components[Ctor.name], inst; if (Ctor.prototype && Ctor.prototype.render) { inst = new Ctor(props, context); Component.call(inst, props, context); } else { // 對應(yīng)函數(shù)組件 inst = new Component(props, context); inst.constructor = Ctor; inst.render = doRender; } if (list) { for (let i = list.length; i--;) { if (list[i].constructor === Ctor) { inst.nextBase = list[i].nextBase; list.splice(i, 1); break; } } } return inst; }setState的處理
更改組件上的state,然后將要渲染的組件放在一個數(shù)組中,在下一次event loop的時候渲染:
setState: function setState(state, callback) { let s = this.state; if (!this.prevState) this.prevState = extend({}, s); extend(s, typeof state === "function" ? state(s, this.props) : state); if (callback)(this._renderCallbacks = this._renderCallbacks || []).push(callback); enqueueRender(this); }, function enqueueRender(component) { // component._dirty為false且items原本為空數(shù)組就能渲染 if (!component._dirty && (component._dirty = true) && items.push(component) == 1) { (options.debounceRendering || defer)(rerender); //異步的執(zhí)行render,要執(zhí)行render方法的component中的_dirty設(shè)為true } }, function rerender() { let p, list = items; items = []; while (p = list.pop()) { if (p._dirty) renderComponent(p); } }preact對事件的處理
preact為了減少增減事件對性能和內(nèi)存的影響,當為dom做事件監(jiān)聽時,添加的是一個代理函數(shù)。
function setAccessor(node, name, old, value, isSvg) { // ... if (name[0] == "o" && name[1] == "n") { let useCapture = name !== (name = name.replace(/Capture$/, "")); name = name.toLowerCase().substring(2); if (value) { if (!old) node.addEventListener(name, eventProxy, useCapture); } else { node.removeEventListener(name, eventProxy, useCapture); } (node._listeners || (node._listeners = {}))[name] = value; } // ... }
function eventProxy(e) { return this._listeners[e.type](options.event && options.event(e) || e); }fiber(個人理解)
從以上源碼閱讀中我們可以看到,react最大的性能問題在于遞歸的diff,react中的shouldCompnentUpdate與PureComponent也是為了緩解這個問題。但是當應(yīng)用比較大的時候一個高級別組件的diff還是很容易使得動畫掉幀。
fiber的出現(xiàn)就是為了解決這個問題,react fiber將計算工作分成了多個小片,這使得整個計算工作可以暫停,中止,或重新開始。為不同類型的更新分配優(yōu)先級。當動畫或用戶交互觸發(fā)時,就可以先暫停低優(yōu)先級的更新工作,保證動畫的流暢性,等所有的渲染計算工作完成,對dom更新進行一次commit。
參考https://calendar.perfplanet.c...
https://reactjs.org/docs/impl...
https://segmentfault.com/a/11...
https://www.w3ctech.com/topic...
https://zhuanlan.zhihu.com/p/...
https://github.com/acdlite/re...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/95133.html
摘要:是一個最小的庫,但由于其對尺寸的追求,它的很多代碼可讀性比較差,市面上也很少有全面且詳細介紹的文章,本篇文章希望能幫助你學(xué)習(xí)的源碼。建議與源碼一起閱讀本文。 作為一名前端,我們需要深入學(xué)習(xí)react的運行機制,但是react源碼量已經(jīng)相當龐大,從學(xué)習(xí)的角度,性價比不高,所以學(xué)習(xí)一個react mini庫是一個深入學(xué)習(xí)react的一個不錯的方法。 preact是一個最小的react mi...
摘要:最后刪除新的樹中不存在的節(jié)點。而中會記錄對其做了相應(yīng)的優(yōu)化,節(jié)點的的情況下,不做移動操作。這種情況,在中得到了優(yōu)化,通過四個指針,在每次循環(huán)中先處理特殊情況,并通過縮小指針范圍,獲得性能上的提升。 上篇文章已經(jīng)介紹過idff的處理邏輯主要分為三塊,處理textNode,element及component,但具體怎么處理component還沒有詳細介紹,接下來講一下preact是如何處理...
摘要:基本介紹選擇式排序也屬于內(nèi)部排序法,是從欲排序的數(shù)據(jù)中,按指定的規(guī)則選出某一元素,再依規(guī)定交換位置后達到排序的目的。而移動次數(shù)與序列的初始排序有關(guān)。空間復(fù)雜度簡單選擇排序需要占用個臨時空間,在交換數(shù)值時使用。 showImg(https://img-blog.csdnimg.cn/20190509221741422.gif); showImg(https://segmentfault....
摘要:,,面向切面編程。,切點,切面匹配連接點的點,一般與切點表達式相關(guān),就是切面如何切點。例子中,注解就是切點表達式,匹配對應(yīng)的連接點,通知,指在切面的某個特定的連接點上執(zhí)行的動作。,織入,將作用在的過程。因為源碼都是英文寫的。 之前《零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)》詳細講了Spring容器的初始化和加載的原理,后面《你真的完全了解Java動態(tài)代理嗎?看這篇就夠了》介紹了下...
摘要:的選擇器允許單個線程監(jiān)視多個輸入通道。一旦執(zhí)行的線程已經(jīng)超過讀取代碼中的某個數(shù)據(jù)片段,該線程就不會在數(shù)據(jù)中向后移動通常不會。 1、引言 很多初涉網(wǎng)絡(luò)編程的程序員,在研究Java NIO(即異步IO)和經(jīng)典IO(也就是常說的阻塞式IO)的API時,很快就會發(fā)現(xiàn)一個問題:我什么時候應(yīng)該使用經(jīng)典IO,什么時候應(yīng)該使用NIO? 在本文中,將嘗試用簡明扼要的文字,闡明Java NIO和經(jīng)典IO之...
閱讀 2320·2021-11-08 13:13
閱讀 1250·2021-10-09 09:41
閱讀 1693·2021-09-02 15:40
閱讀 3193·2021-08-17 10:13
閱讀 2551·2019-08-29 16:33
閱讀 3126·2019-08-29 13:17
閱讀 3137·2019-08-29 11:00
閱讀 3301·2019-08-26 13:40