1.react 我們應(yīng)該盡量放在cdn
ReactDOM.render會選擇一個元素節(jié)點,然后把react元素寫進去
一個react JSX元素也是一個對象
多次render會重新更新界面丑孩,且只更新變動的部分,
diff算法:
可以用一個function來定義一個組件李皇,也可以用class來定義,es6的class其實是一個語法糖宙枷,繼承模型還是基于原型鏈掉房,他的本質(zhì)其實是一個function
當一個對象調(diào)用靜態(tài)或原型方法時,如果該對象沒有“this”值(或“this”作為布爾慰丛,字符串卓囚,數(shù)字,未定義或null)?诅病,那么“this”值在被調(diào)用的函數(shù)內(nèi)部將為?undefined哪亿。不會發(fā)生自動包裝。即使我們以非嚴格模式編寫代碼贤笆,它的行為也是一樣的蝇棉,因為所有的函數(shù)、方法芥永、構(gòu)造函數(shù)篡殷、getters或setters都在嚴格模式下執(zhí)行。因此如果我們沒有指定this的值恤左,this值將為undefined贴唇。
如果我們使用傳統(tǒng)的基于函數(shù)的類來編寫上述代碼,那么基于調(diào)用該函數(shù)的“this”值將發(fā)生自動裝箱飞袋。
props是什么,是react組建的屬性链患,只讀
使用class改寫function
引入state
將生命周期方法添加到 Class 中,生命周期和setState
1麻捻、初始化:初始進入頁面 → constructor → componentWillMount → render → componentDidMount → componentWillUnmount纲仍;
這里需要注意的是:componentWillMount中若使用setState,其state會被合并到初始數(shù)據(jù)當中贸毕。那么郑叠,react是怎么樣處理合并的呢?為什么要這樣處理呢明棍?在componentDidMount中乡革,state又是怎么處理的?本文會在下面講解生命周期流程的部分,來解答說明沸版。
2嘁傀、更新:setState → componentWillReceiveProps → shouldComponentUpdate → componentWillUpdate → render → componentDidUpdate → componentWillUnmount。
更新流程需要提到兩點:一點是componentWillReceiveProps中使用setState视粮,state會被收集儲存起來细办,這里是區(qū)別于上面componentWillMount中state合并到初始數(shù)據(jù)中的。這里提一下:shouldComponentUpdate如果return => false蕾殴,則不會執(zhí)行更新(render)笑撞。
1、首先钓觉,進入頁面娃殖,會初始化頁面數(shù)據(jù)(state, props, context等…),等待備用议谷;
2炉爆、然后,設(shè)置生命狀態(tài)為:MOUNTING卧晓,這個狀態(tài)下面會說明它的用途芬首,這里我們先按照流程繼續(xù)往下走;
3逼裆、接下來郁稍,在componentWillMount中,setState操作胜宇,只是把state合并到初始化狀態(tài)中顷窒,而根本不會觸發(fā)render 淹父;在這里更新state,就等同于直接寫在this.state中,所以治筒,在此生命周期中的setState根本沒有意義;
4果元、執(zhí)行到這里契耿,生命狀態(tài) 會被重置為 null,之后是渲染頁面(即執(zhí)行render)系洛;
5俊性、最后,渲染完以后描扯,執(zhí)行componentDidMount定页,這里使用setState即會正常觸發(fā)重新渲染了,更新state绽诚。(接下來典徊,就是更新流程了:技濉!)
1宫峦、首先岔帽,react會比較前后元素、狀態(tài)等是否不同导绷,如果不同則正式發(fā)起更新犀勒;
2、然后妥曲,生命狀態(tài) 被設(shè)置為RECEIVE_PROPS(注意:此時生命周期中贾费,setState不會觸發(fā)更新,而是會做其他處理)檐盟;
3褂萧、接下來,componentWillReceiveProps中的setState就不會執(zhí)行更新葵萎,而是合并掛載起來导犹,等待render時統(tǒng)一更新;
4羡忘、到這里谎痢,生命狀態(tài) 會重置為null;然后shouldComponentUpdate中會判斷是否更新卷雕;之后是componentWillUpdate节猿。
敲黑板了!B瘛1踔觥! ?shouldComponentUpdate和componentWillUpdate執(zhí)行的時候浸间,生命狀態(tài) 已經(jīng)被重置為null太雨,在它們里面的setState會觸發(fā)更新,那么在其間使用呢发框?會造成什么躺彬?答案就是:在一個更新周期還沒有render之前,再次發(fā)起updateComponent梅惯,直接導(dǎo)致遞歸更新,死循環(huán)仿野!相信我铣减!等待你的,就是瀏覽器崩潰=抛鳌葫哗!所以在他們里面??禁止??使用setState缔刹。
5、最后劣针,渲染頁面校镐;再執(zhí)行componentDidUpdate;它里面執(zhí)行setState捺典,會觸發(fā)更新鸟廓,不同的是render完成之后再發(fā)起的reRender。雖然這兒區(qū)別于上面兩個生命周期中使用的情況襟己,但是會一遍一遍的更新引谜,這肯定也是不合理的,所以需要有條件的使用setState擎浴。
最后呢员咽,簡單介紹一下,退出頁面的流程贮预。此流程中贝室, 首先生命狀態(tài)也會被賦予值為UNMOUNTING, 然后執(zhí)行componentWillUnmount仿吞,最后生命狀態(tài)重置為null滑频,做卸載頁面組件和狀態(tài)等處理。順便提一下茫藏,在componentWillUnmount中使用setStat误趴,因為等待的是頁面卸載,所以改變state是沒有意義的务傲。
生命周期中setState的使用情況:
????無意義使用:componentWillMount凉当,componentWillUnmount;
????有條件使用:componentDidUpdate售葡;
????禁止使用:componentWillUpdate看杭,shouldComponentUpdate;
????正常使用:componentWIllReceiveProps挟伙,componentDidMount楼雹。
生命周期中setState是否觸發(fā)更新:
????componentWillMount和componentWillReceiveProps中,setState會被react內(nèi)部處理尖阔,而不觸發(fā)render贮缅;
????其他生命周期均正常出發(fā)更新渲染。
setState的執(zhí)行原理介却,可以分為兩類:
1谴供、批量更新類:即react內(nèi)部的執(zhí)行函數(shù),執(zhí)行setState的執(zhí)行邏輯齿坷,都是批量更新處理桂肌,其中包括:react內(nèi)部事件(合成事件)和生命周期数焊;
2、非批量更新類:即上面兩種情況以外的情況崎场,經(jīng)常見到的:原生事件佩耳、setTimeout、fetch等等谭跨;
再講解之前干厚,先說明兩個概念:
1、事務(wù):可以理解為饺蚊,一個正常的函數(shù)外層又被包裹了一層萍诱。這層包裹處理,包括一個或多個的函數(shù)執(zhí)行前的處理函數(shù)(initialize函數(shù))污呼、一個和多個函數(shù)執(zhí)行后的處理函數(shù)(close函數(shù))裕坊;React很多的邏輯處理,都使用了事務(wù)的概念燕酷;
2籍凝、合成事件和原生事件的關(guān)系和區(qū)別:
區(qū)別:原生事件就是addEventListener寫法的事件!而合成事件苗缩,就是直接書寫react中的onClick饵蒂、onChange等;
關(guān)系:合成事件可以理解為react對原生事件的包裹封裝酱讶;原生事件相當于上面事務(wù)概念中的正常的函數(shù)退盯,而經(jīng)過包裝處理形成的事務(wù),就是react中的合成事件泻肯。
事實上渊迁,每個setState都是會直接觸發(fā)render更新的。只是react經(jīng)過內(nèi)部處理灶挟,讓它在一些情況下不會觸發(fā)render(生命周期已說明)琉朽;還有一些情況,就是同事存在多個setState的時候稚铣,不是每個setState都會觸發(fā)箱叁,而是將state統(tǒng)一收集起來,進行統(tǒng)一render處理
isBatchedUpdates是批量更新狀態(tài)惕医,通過修改它來開啟和關(guān)閉批量更新耕漱;updateComponent函數(shù)內(nèi)部執(zhí)行的是上面生命周期的更新流程
原生事件中,setState會直接觸發(fā)render更新抬伺,所以栗子在原生事件中的執(zhí)行順序是孤个,先render然后執(zhí)行callback,setState事務(wù)執(zhí)行完畢沛简,然后執(zhí)行打印齐鲤。打印拿到的就是setState更新之后的狀態(tài),以此類推椒楣,所以出現(xiàn)了上面原生事件的打印順序给郊,這就很明了了。
而合成事件則不然捧灰,它直接發(fā)起事務(wù)1淆九,在函數(shù)執(zhí)行之前開始批量更新狀態(tài)(isBatchedUpdates為true,默認值是false毛俏!)炭庙,開啟之后,執(zhí)行合成事件中的setState煌寇,此時處于批量更新狀態(tài)焕蹄,這時setState不會觸發(fā)render更新,而是做了兩件事情:收集state和callback阀溶。這里我貼上幾行源碼腻脏,有助于理解:
默認批量更新是處于關(guān)閉的狀態(tài),那么會直接執(zhí)行batchedUpdates(此函數(shù)就是更新渲染函數(shù))银锻。這里就是批量更新狀態(tài)是否開啟的分叉口:當開啟批量更新時永品,則是把狀態(tài)push到數(shù)組(dirtyComponents)中。那么收集完成击纬,在哪里處理呢鼎姐?我們繼續(xù)往下看。
依照上面的流程圖更振,收集完狀態(tài)以后炕桨,執(zhí)行事務(wù)的close函數(shù),它里面做了些什么呢殃饿?一個是關(guān)閉批量更新狀態(tài)谋作,一個是正式發(fā)起對收集的狀態(tài)的處理,這里又開啟了一個新事務(wù):即事務(wù)2乎芳。事務(wù)2遵蚜,經(jīng)過復(fù)雜的處理,處理更新了收集的state奈惑,也就是dirtyComponents吭净。處理完以后,執(zhí)行事務(wù)2的close函數(shù)肴甸,它重置了整個更新的狀態(tài)寂殉,也是在這里處理執(zhí)行事務(wù)1中收集的callback;
讓我們回頭看看上面的栗子
setState只是收集了state和callback原在,并沒有做其他處理友扰,然后直接執(zhí)行了下面的console彤叉,所以!村怪!這時的num一定是初始值1秽浇,然后下面繼續(xù)收集,再下面console還是1甚负;
當收集完以后柬焕,render!梭域!
最后處理callback斑举,也就執(zhí)行了callback里面的console。
到這里在兩種執(zhí)行場景下面的setState的執(zhí)行邏輯就完全講完了病涨。這里說到了一些源碼富玷,但只是順著setState這條線進行了分析說明,歡迎同學們更深層次的研究没宾!
最后凌彬,總結(jié)一下setState:
1、setState的執(zhí)行循衰,分為兩大類:一類是生命周期和合成函數(shù)铲敛;一類是非前面的兩種情況;
2会钝、兩種類型下伐蒋,setState都是同步執(zhí)行,只是在批量更新類中迁酸,state和callback被收集起來延遲處理了先鱼,可以理解為數(shù)據(jù)的異步執(zhí)行;而非批量更新類中的setState直接觸發(fā)更新渲染奸鬓。
3焙畔、callback與state同時收集,處理是在render之后串远,統(tǒng)一處理的宏多。
原文1:http://www.reibang.com/p/e09cbecca1d1
原文2:http://www.reibang.com/p/cdb4ad82df20
原文3:https://zh-hans.reactjs.org/docs/components-and-props.html