亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

幫你讀懂preact源碼(三)

yuanxin / 3558人閱讀

摘要:對(duì)回收的處理在中,回收調(diào)用了兩個(gè)方法,節(jié)點(diǎn)的回收一般會(huì)調(diào)用,組件的回收會(huì)調(diào)用。個(gè)人理解從以上源碼閱讀中我們可以看到,最大的性能問(wèn)題在于遞歸的,中的與也是為了緩解這個(gè)問(wèn)題。為不同類型的更新分配優(yōu)先級(jí)。

對(duì)回收的處理

在preact中,回收調(diào)用了兩個(gè)方法,dom節(jié)點(diǎn)的回收一般會(huì)調(diào)用recollectNodeTree,組件的回收會(huì)調(diào)用unmountComponent。

preact復(fù)用dom的秘密在于當(dāng)要卸載一個(gè)組件的時(shí)候,只有組件的根節(jié)點(diǎn)會(huì)從父節(jié)點(diǎn)上卸載掉,組件完整的dom仍然存在,被卸載的組件會(huì)保存在components對(duì)象中。

在創(chuàng)建組件的時(shí)候又通過(guò)nodeName拿到對(duì)應(yīng)的dom節(jié)點(diǎn)樹,掛載在組件實(shí)例的inst.nextBase上,在renderComponent的時(shí)候,再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 { // 對(duì)應(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,然后將要渲染的組件放在一個(gè)數(shù)組中,在下一次event loop的時(shí)候渲染:

    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對(duì)事件的處理

preact為了減少增減事件對(duì)性能和內(nèi)存的影響,當(dāng)為dom做事件監(jiān)聽時(shí),添加的是一個(gè)代理函數(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(個(gè)人理解)

從以上源碼閱讀中我們可以看到,react最大的性能問(wèn)題在于遞歸的diff,react中的shouldCompnentUpdate與PureComponent也是為了緩解這個(gè)問(wèn)題。但是當(dāng)應(yīng)用比較大的時(shí)候一個(gè)高級(jí)別組件的diff還是很容易使得動(dòng)畫掉幀。

fiber的出現(xiàn)就是為了解決這個(gè)問(wèn)題,react fiber將計(jì)算工作分成了多個(gè)小片,這使得整個(gè)計(jì)算工作可以暫停,中止,或重新開始。為不同類型的更新分配優(yōu)先級(jí)。當(dāng)動(dòng)畫或用戶交互觸發(fā)時(shí),就可以先暫停低優(yōu)先級(jí)的更新工作,保證動(dòng)畫的流暢性,等所有的渲染計(jì)算工作完成,對(duì)dom更新進(jìn)行一次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)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

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

相關(guān)文章

  • 幫你讀懂preact源碼(一)

    摘要:是一個(gè)最小的庫(kù),但由于其對(duì)尺寸的追求,它的很多代碼可讀性比較差,市面上也很少有全面且詳細(xì)介紹的文章,本篇文章希望能幫助你學(xué)習(xí)的源碼。建議與源碼一起閱讀本文。 作為一名前端,我們需要深入學(xué)習(xí)react的運(yùn)行機(jī)制,但是react源碼量已經(jīng)相當(dāng)龐大,從學(xué)習(xí)的角度,性價(jià)比不高,所以學(xué)習(xí)一個(gè)react mini庫(kù)是一個(gè)深入學(xué)習(xí)react的一個(gè)不錯(cuò)的方法。 preact是一個(gè)最小的react mi...

    XboxYan 評(píng)論0 收藏0
  • 幫你讀懂preact源碼(二)

    摘要:最后刪除新的樹中不存在的節(jié)點(diǎn)。而中會(huì)記錄對(duì)其做了相應(yīng)的優(yōu)化,節(jié)點(diǎn)的的情況下,不做移動(dòng)操作。這種情況,在中得到了優(yōu)化,通過(guò)四個(gè)指針,在每次循環(huán)中先處理特殊情況,并通過(guò)縮小指針?lè)秶?,獲得性能上的提升。 上篇文章已經(jīng)介紹過(guò)idff的處理邏輯主要分為三塊,處理textNode,element及component,但具體怎么處理component還沒(méi)有詳細(xì)介紹,接下來(lái)講一下preact是如何處理...

    Warren 評(píng)論0 收藏0
  • 數(shù)據(jù)結(jié)構(gòu)與算法():帶你讀懂選擇排序(Selection sort)

    摘要:基本介紹選擇式排序也屬于內(nèi)部排序法,是從欲排序的數(shù)據(jù)中,按指定的規(guī)則選出某一元素,再依規(guī)定交換位置后達(dá)到排序的目的。而移動(dòng)次數(shù)與序列的初始排序有關(guān)??臻g復(fù)雜度簡(jiǎn)單選擇排序需要占用個(gè)臨時(shí)空間,在交換數(shù)值時(shí)使用。 showImg(https://img-blog.csdnimg.cn/20190509221741422.gif); showImg(https://segmentfault....

    Kaede 評(píng)論0 收藏0
  • 源碼入手,一文帶你讀懂Spring AOP面向切面編程

    摘要:,,面向切面編程。,切點(diǎn),切面匹配連接點(diǎn)的點(diǎn),一般與切點(diǎn)表達(dá)式相關(guān),就是切面如何切點(diǎn)。例子中,注解就是切點(diǎn)表達(dá)式,匹配對(duì)應(yīng)的連接點(diǎn),通知,指在切面的某個(gè)特定的連接點(diǎn)上執(zhí)行的動(dòng)作。,織入,將作用在的過(guò)程。因?yàn)樵创a都是英文寫的。 之前《零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)》詳細(xì)講了Spring容器的初始化和加載的原理,后面《你真的完全了解Java動(dòng)態(tài)代理嗎?看這篇就夠了》介紹了下...

    wawor4827 評(píng)論0 收藏0
  • 少啰嗦!一分鐘帶你讀懂Java的NIO和經(jīng)典IO的區(qū)別

    摘要:的選擇器允許單個(gè)線程監(jiān)視多個(gè)輸入通道。一旦執(zhí)行的線程已經(jīng)超過(guò)讀取代碼中的某個(gè)數(shù)據(jù)片段,該線程就不會(huì)在數(shù)據(jù)中向后移動(dòng)通常不會(huì)。 1、引言 很多初涉網(wǎng)絡(luò)編程的程序員,在研究Java NIO(即異步IO)和經(jīng)典IO(也就是常說(shuō)的阻塞式IO)的API時(shí),很快就會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題:我什么時(shí)候應(yīng)該使用經(jīng)典IO,什么時(shí)候應(yīng)該使用NIO? 在本文中,將嘗試用簡(jiǎn)明扼要的文字,闡明Java NIO和經(jīng)典IO之...

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

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

0條評(píng)論

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