兩年React前端開發(fā)總結(jié)

不同數(shù)據(jù)管理的意義

? ? state、redux等數(shù)據(jù)管理都有各自的意義,不要盲目使用state或redux
? ? 1. state:react是數(shù)據(jù)驅(qū)動更新,state更新會重新觸發(fā)render進(jìn)行頁面更新,不要將與頁面更新無關(guān)的數(shù)據(jù)也存放在state中,state是驅(qū)動數(shù)據(jù),不僅僅只是單純的數(shù)據(jù)概念
? ? 2.redux:redux主要是解決跨多層組件之間的數(shù)據(jù)共享,使用redux管理數(shù)據(jù)需要相關(guān)的reducer、action、connect、mapStateToProps/mapDispatchToProps等,不得不說引入redux會使得代碼可讀性降低,在開發(fā)中應(yīng)該盡量少使用redux管理數(shù)據(jù),對于跨越一兩層組件且共享組件較少的數(shù)據(jù)利用props傳遞更加方便快捷(見識過將所有數(shù)據(jù)放在redux中維護(hù)的組件,state幾乎都廢棄了)
? ? 3.Form.create():antd(下面所講特指3.x版本使用方法) Form組件提供的可獨立管理多個表單項數(shù)據(jù)的機(jī)制,能夠大大減少人工管理表單的變量與表單項數(shù)據(jù)處理邏輯,極力推薦,創(chuàng)建form實例通過props注入到組件中,靈活的getFieldDecorator方法可進(jìn)行零散的收集需要綁定的表單項(甚至可以跨越組件進(jìn)行收集綁定),在以大量表單為主的中后臺系統(tǒng)可以看作是另一種獨立的數(shù)據(jù)狀態(tài)管理器

組件封裝、模塊拆分

? ? ?這是很重要且有意義的,開發(fā)中一定要注意避免大組件(數(shù)千行),合理對大組件進(jìn)行模塊拆分,不同模塊組件盡可能將各自功能內(nèi)聚,減少對外部的依賴,父組件僅用來處理公共事件與子組件的交互即可

與組件實例無關(guān)或關(guān)聯(lián)教少的工具函數(shù)/教大靜態(tài)數(shù)據(jù)放在組件外部定義(當(dāng)組件復(fù)用時能減少代碼運行體積)

數(shù)據(jù)解構(gòu)與賦值

? ? 避免直接使用 data.a.b.c.d 的方式直接讀取值,容易造成取值錯誤而頁面崩潰。使用數(shù)據(jù)解構(gòu)時結(jié)合賦初始值來避免這種錯誤(也可使用lodash.get):

數(shù)據(jù)解構(gòu)與賦初始值

&& || 與三目

某些場景使用邏輯運算符 && 和 || 以及三目運算符 替代if else 更簡潔


語義化使用map、filter、reduce、some等函數(shù)

?語義化不僅僅只體現(xiàn)在html標(biāo)簽中,我們的所有代碼都應(yīng)具有相應(yīng)的語義,從語義化html標(biāo)簽、map等語義函數(shù),甚至到變量命名、組件模塊劃分、項目目錄規(guī)劃都應(yīng)在閱讀代碼時體現(xiàn)相應(yīng)語義

react中的key

合理改變key強(qiáng)制組件進(jìn)行刷新,可減少部分代碼邏輯
? ? 比如hooks中僅在創(chuàng)建時執(zhí)行一次的useState或者表單的初始值賦值(以props傳入的值作為初始值),這些初始值在組件更新期間并不會再次生效(即使依賴數(shù)據(jù)改變了),按正常操作,我們需要在componentWillReceiveProps或者在useEffect中監(jiān)聽傳入的props依賴是否變化來對state數(shù)據(jù)或表單值進(jìn)行更改,另一種偷懶方法就是利用key的變化來強(qiáng)制組件重新進(jìn)行加載,當(dāng)依賴的props數(shù)據(jù)改變,在父組件中改變子組件key來強(qiáng)制子組件重新加載

可使用setTimeout將某些操作放入異步任務(wù)中延后執(zhí)行,在開發(fā)中可以使用這個騷操作(少用)
? ? 注意在js中只有setTimeout與Promise回調(diào)才是真正意義上的異步事件,這些事件回調(diào)最終會放入瀏覽器渲染進(jìn)程下的事件觸發(fā)線程中去等待js引擎線程執(zhí)行完畢后再去輪詢執(zhí)行。
? ? 對于setState所說的同步異步與上面所說完全不是一回事,這里的異步只是react內(nèi)部實現(xiàn)的state批量更新機(jī)制,其實并不能稱為異步,只是給我們的感覺像是異步。


React數(shù)據(jù)驅(qū)動概念

?把這兩個詞拆開來理解:數(shù)據(jù)與驅(qū)動
?React中進(jìn)行驅(qū)動的數(shù)據(jù)容易想到的是state,當(dāng)然也包含props;驅(qū)動可以理解為觸發(fā)render進(jìn)行頁面更新渲染。后者是框架自動實現(xiàn)的,所以React開發(fā)中的關(guān)注點是數(shù)據(jù)。
? ? 一個組件在首次進(jìn)行加載時會走一遍render,再之后該組件實例的state與props更改都會觸發(fā)render,但state與props的改變并不一定會觸發(fā)組件的render,因為React為了降低對前后數(shù)據(jù)比對的性能開銷采取了數(shù)據(jù)的淺比對,僅對前后state或前后props數(shù)據(jù)的第一層進(jìn)行淺比較,所以可以進(jìn)一步理解為是state與props數(shù)據(jù)對象中的第一層屬性數(shù)據(jù)的在驅(qū)動React組件的更新

state更改

react不建議直接修改state,開發(fā)中如果直接修改state容易造成bug(特指手動修改嵌套層次較深的state數(shù)據(jù)),要注意繼承PureComponent的組件由于重寫了SCU,會對state與props進(jìn)行淺比對可能會導(dǎo)致SCU返回false而不進(jìn)行頁面更新,如果手動修改了state在setState時需重新申明新數(shù)組或?qū)ο筮M(jìn)行數(shù)據(jù)更新才能觸發(fā)頁面更新:

state改變方式

大表單數(shù)據(jù)收集

? ? 開發(fā)場景:在開發(fā)中后臺應(yīng)用時,常常會有收集和回填大表單的需求,新建一個任務(wù)時會有很多表單數(shù)據(jù)需要收集,而且此數(shù)據(jù)不僅僅限于form等表單項,還可能是其它控件:Table中的數(shù)據(jù),而且對于大表單往往需要將模塊進(jìn)行拆分,在最終收集數(shù)據(jù)時需要收集各個模塊中的數(shù)據(jù),如何組織代碼邏輯能夠高效進(jìn)行各模塊的數(shù)據(jù)收集匯總,我通常有兩種方式:1. 通過ref;2.通過自定義表單控件;

? ? 1.通過ref:每個子表單組件模塊維護(hù)各自的表單數(shù)據(jù),每次表單控件值改變時將最新的表單值匯總到該組件state中進(jìn)行保存,定義一個獲取并返回該模塊所有表單數(shù)據(jù)的函數(shù),該函數(shù)本組件并不調(diào)用,而是提供給父組件利用ref來獲取該子模塊的表單數(shù)據(jù),這樣在提交整體大表單時父組件可利用ref獲取每一個子表單組件的數(shù)據(jù)進(jìn)行匯總處理。這種方法在父組件獲取各個子表單數(shù)據(jù)時特別簡單粗暴。

? ? 2.通過自定義表單控件:這種方式基于antd的Form.create()(FormComp)高階組件,F(xiàn)orm.create創(chuàng)建了一個獨立的form實例用來管理使用getFieldDecorator()綁定的表單控件(或者自定義表單控件),其重寫了表單控件的onChange事件,并結(jié)合每個表單控件的value實現(xiàn)了form實例與各表單控件的雙向綁定(form實例可利用setFieldsValue一系列api改變各個表單控件的value,另一方面每個表單控件的改變觸發(fā)onChange也會改變form實例內(nèi)保存的相應(yīng)表單控件的value)。基于以上特性,我們只需將在父組件中通過Form.create創(chuàng)建的form實例提供的getFieldDecorator分發(fā)到各個子表單模塊中就能自動完成對所有子表單數(shù)據(jù)收集,在提交時利用form.getFieldsValue就能獲取到所有的表單數(shù)據(jù)。這種方式的優(yōu)勢在于一旦完成各表單項綁定,收集與校驗邏輯在表單控件改變時就自動完成了。


數(shù)據(jù)請求延遲的bug與useEffect中的函數(shù)防抖失效原因

場景:對于帶有多個篩選條件的Table,當(dāng)條件改變時就發(fā)送request請求table數(shù)據(jù),但有時由于網(wǎng)絡(luò)延遲會使得先請求的request返回數(shù)據(jù)較晚,導(dǎo)致渲染的table數(shù)據(jù)不正確

解決方法:使用hook的useEffect監(jiān)控篩選條件的改變,當(dāng)條件改變時去就發(fā)送請求,為了緩解間隔較短的多次請求因網(wǎng)絡(luò)延遲造成拿不到最后一次請求的數(shù)據(jù),將useEffect內(nèi)部執(zhí)行的request函數(shù)做下防抖

tip: 防抖只能緩解由于網(wǎng)絡(luò)延遲造成的bug,即使在網(wǎng)絡(luò)狀況良好情況下,加上防抖也可以減少不必要的請求,也是一種優(yōu)化

不做防抖


做防抖的情況


useCallback與useMemo

? hooks中使用useCallback與useMemo對數(shù)據(jù)與函數(shù)進(jìn)行緩存,避免在給子組件傳遞數(shù)據(jù)與函數(shù)時造成子組件無謂刷新

不使用useCallback與useMemo


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

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