react+redux+webpack移動(dòng)端項(xiàng)目總結(jié)

前言

距離我進(jìn)新公司也有一個(gè)多月,這一個(gè)月的事件使用react寫(xiě)了一個(gè)項(xiàng)目焙蹭,期間斷斷續(xù)續(xù)重構(gòu)了兩三次,目前已經(jīng)完成第一階段測(cè)試嫂伞,也總結(jié)分享一些使用react的一些坑壳嚎。

react

先啰嗦幾句講一下react原理,新人可以認(rèn)真看下末早,老鳥(niǎo)可跳過(guò)烟馅。

react并沒(méi)有像其他如vue,ng一樣采用MVVM模式,所謂MVVM模式然磷,狹義來(lái)說(shuō)就是將模板與數(shù)據(jù)綁定在一起郑趁,當(dāng)數(shù)據(jù)發(fā)生改變時(shí),模板自動(dòng)更新姿搜,這是中間的VM寡润,最左邊的M可以理解為我們看到的頁(yè)面,而最右邊的M可以理解為原始數(shù)據(jù)(例如數(shù)據(jù)庫(kù)數(shù)據(jù))舅柜。
其實(shí)要知道梭纹,這些框架模式歸根結(jié)底的目的希望使代碼更容易開(kāi)發(fā)和維護(hù)。當(dāng)你寫(xiě)一個(gè)小頁(yè)面你不覺(jué)得什么致份,但是當(dāng)你的頁(yè)面越來(lái)越龐大变抽,越來(lái)越復(fù)雜,開(kāi)發(fā)人員走了一批又一批的時(shí)候,你就會(huì)明白了绍载。而如何解決诡宗,現(xiàn)在比較公認(rèn)的理念一個(gè)是組件化,將頁(yè)面拆分成一個(gè)個(gè)組件击儡,其實(shí)拆分成組件的目的并不全是為了復(fù)用塔沃,我覺(jué)得更多是為了維護(hù);一個(gè)就是希望讓?xiě)?yīng)用層的編程能更專(zhuān)注于業(yè)務(wù)邏輯阳谍,那么這些框架都去做了處理蛀柴,減少了大量DOM操作,讓業(yè)務(wù)開(kāi)發(fā)更加專(zhuān)注矫夯。

那么我們看看react采用的是什么原理鸽疾。其實(shí)react采用的方法簡(jiǎn)單粗暴:它并沒(méi)有對(duì)模板做數(shù)據(jù)綁定,而是每當(dāng)數(shù)據(jù)變化時(shí)茧痒,就重新渲染模板。這有一個(gè)很大的好處就是每當(dāng)數(shù)據(jù)變化時(shí)融蹂,對(duì)頁(yè)面來(lái)說(shuō)只有一次IO操作旺订,而單純的雙向綁定更新DOM會(huì)有很多次;但有一個(gè)問(wèn)題超燃,如果只改變了一個(gè)dom的數(shù)據(jù)区拳,整個(gè)模板都會(huì)重新渲染。那react解決的方法是每當(dāng)數(shù)據(jù)改變時(shí)意乓,就進(jìn)行對(duì)比樱调。

那么該如何對(duì)比呢,最簡(jiǎn)單的方法是每當(dāng)數(shù)據(jù)改變届良,就去頁(yè)面獲取相應(yīng)的DOM信息笆凌,然后與現(xiàn)在的DOM信息做比較。這個(gè)方法有個(gè)致命的缺點(diǎn)就是每次有DOM改變士葫,就會(huì)有許多讀取操作乞而,IO操作太多,很影響性能慢显。那么可以通過(guò)空間換時(shí)間的方法爪模,將DOM信息保存起來(lái),就避免了去頁(yè)面獲取信息的IO操作荚藻。那么我們看看一個(gè)真實(shí)DOM有多少數(shù)據(jù)

domproperty.png

虛擬DOM

如果我們把所有原生DOM緩存起來(lái)進(jìn)行比較顯然內(nèi)存會(huì)爆炸屋灌,而我們所需要的僅僅是幾個(gè)為數(shù)不多的狀態(tài)信息(例如style啊這些),這時(shí)虛擬DOM應(yīng)運(yùn)而生应狱,如果說(shuō)原生DOM是一塊豬肉共郭,那么虛擬DOM就是這塊豬肉中多精肉,他剔除了那些對(duì)我們來(lái)說(shuō)沒(méi)有太多意義相反還占內(nèi)存的狀態(tài)信息,而只將我們所需要的內(nèi)容留了下來(lái)落塑。那虛擬DOM該如何比較呢纽疟,就涉及到了虛擬DOM的diff算法。

diff算法

簡(jiǎn)單來(lái)說(shuō)兩個(gè)模板就像兩棵樹(shù)一樣憾赁,傳統(tǒng)的樹(shù)對(duì)比的時(shí)間復(fù)雜度是O^3污朽,也就是說(shuō)要整棵樹(shù)遍歷三次,那react根據(jù)DOM的特點(diǎn):跨層級(jí)的操作較少龙考。什么叫跨層級(jí)蟆肆,舉個(gè)例子一個(gè)組件有三個(gè)層級(jí)關(guān)系(嵌套三層),把第二層的div放到第三層就屬于跨層級(jí)操作晦款。這種操作其實(shí)還是比較少的炎功,react官方也不推薦這么寫(xiě)。那么利用這個(gè)特點(diǎn)缓溅,react只diff同層級(jí)的DOM蛇损。這里涉及以下幾種情況

  1. tag變化(標(biāo)簽變化)
  2. 屬性變化

第二種沒(méi)什么好說(shuō),就是進(jìn)行同層級(jí)對(duì)比坛怪。這里詳細(xì)說(shuō)一下第一種變化淤齐,react的方法是當(dāng)前層級(jí)往下全部刪除替換,簡(jiǎn)單暴力袜匿。在業(yè)務(wù)開(kāi)發(fā)來(lái)看更啄,你同層級(jí)類(lèi)型都不同了,比如div變成了input居灯,那么你的子組件相同的幾率也較小祭务,因此不如整個(gè)替換簡(jiǎn)單暴力。同時(shí)這也說(shuō)明為什么列表需要key屬性怪嫌,因?yàn)榱斜砗芏嗟膭h除操作對(duì)于react來(lái)說(shuō)是不知道的义锥,它需要一個(gè)key來(lái)了解到底誰(shuí)是誰(shuí)。

踩過(guò)的一些坑

state

作為前端岩灭,拿到原型第一件事就是要與你的產(chǎn)品充分溝通缨该,評(píng)估該項(xiàng)目是否需要引入redux,那么如何確定需要引入redux呢川背,這邊有幾點(diǎn):

  1. 頁(yè)面之間組件之間通信較多贰拿,且是跨層級(jí)的;
  2. 頁(yè)面的交互邏輯較復(fù)雜熄云,且經(jīng)常引起多處組件變化膨更。

再然后就是對(duì)state的設(shè)計(jì)。對(duì)于后臺(tái)的返回的數(shù)據(jù)缴允,你并不知道到底哪些是有用的荚守,哪些可能現(xiàn)在沒(méi)用以后有用珍德,因此我的建議是對(duì)于每個(gè)api都將它存在一個(gè)object里。那么組件該如何去獲取矗漾,首先不能全部通過(guò)頂部container獲取依次往下傳锈候,也不能粒度很細(xì)的去一個(gè)個(gè)connect,我的建議是對(duì)于一個(gè)object敞贡,可以用一個(gè)container去connect泵琳,粒度把握主要看你的業(yè)務(wù)需求。

還有一個(gè)要不要全局都使用redux誊役。我的觀(guān)點(diǎn)是否定的获列,我認(rèn)為對(duì)于局部一個(gè)組件內(nèi)的狀態(tài)完全可以通過(guò)setState來(lái)滿(mǎn)足。

圖片處理

首先將圖片做一些劃分蛔垢。例如以500k作為分界击孩,小于500k為小圖片,否則是大圖片鹏漆。對(duì)于小圖片巩梢,我們需要做如下判斷:

  1. 頁(yè)面是否重復(fù)使用?是就用雪碧圖艺玲,否則轉(zhuǎn)base64.
  2. 對(duì)于大圖片括蝠,可以進(jìn)行壓縮后使用。

base64可以用webpack的url-loader替換板驳。
舉個(gè)例子

require('url?limit=250!./xxx.png')
//這里就會(huì)使用url-loader又跛,假如圖片小于250碍拆,就會(huì)轉(zhuǎn)為base64

移動(dòng)端適配

對(duì)于適配若治,我所知比較好的方法是利用rem作為單位,將頁(yè)面寬度等分成10個(gè)rem感混,根據(jù)頁(yè)面動(dòng)態(tài)的用js去改變font-size端幼,達(dá)到適配不同瀏覽器的目的。例如愛(ài)瘋寬320px弧满,那么font-size設(shè)置為32px婆跑。那么10rem就是等于整個(gè)屏幕的寬度。但是有一個(gè)特例就是高清屏庭呜,一般高清屏的物理像素是實(shí)際像素的2倍滑进,那么當(dāng)你想顯示一個(gè)寬度為1的邊框時(shí),在普通屏幕是1px募谎,在高清屏可以有0.5px(問(wèn)題是很多瀏覽器不支持扶关,為將0.5px認(rèn)為是0)。雖然都使用1px在兩者屏幕上實(shí)際上是一樣的数冬,但是高清屏里的1px在射雞師眼里是無(wú)法達(dá)到他對(duì)于1的要求的节槐。于是就有一些解決方案,比較簡(jiǎn)單是是使用transform:scale(0.5)。那么還有一種解決方案就是阿里的移動(dòng)端解決方案铜异,原理是將頁(yè)面整體scale縮小哥倔,然后放大font-size,來(lái)保證rem為單位的布局不變揍庄,但是px為單位的會(huì)被縮小咆蒿。

性能提升

首先先確定需求,確實(shí)有這個(gè)需求的時(shí)候再談币绩。

懶加載

webpack其實(shí)會(huì)幫我們做第三方依賴(lài)的懶加載處理蜡秽,那么針對(duì)react,我們可以通過(guò)現(xiàn)成的庫(kù)來(lái)實(shí)現(xiàn)懶加載react-lazyload,或者使用webpack現(xiàn)成的

require.ensure([],()=>{
require('public.js')
})

來(lái)實(shí)現(xiàn)缆镣。

shouldComponentUpdate

其實(shí)這個(gè)鉤子可以極大的幫助我們?nèi)ヌ嵘阅苎客唬捎谒拇嬖冢覀兛梢宰约号袛嗄男┦俏覀兘M件需要的state董瞻,哪些是不需要的寞蚌,那么這就可以阻止react進(jìn)行不必要diff。但是有一個(gè)問(wèn)題就是對(duì)于對(duì)象我們很難去判斷他們是否相等钠糊,那么可以通過(guò)immutableJs的fromJS和is方法來(lái)解決這個(gè)問(wèn)題挟秤。其實(shí)immutableJs的好處遠(yuǎn)不止于此,目前我也尚在填坑中抄伍。

使用不可變數(shù)據(jù)艘刚,可以更好的達(dá)到函數(shù)式編程,不僅利于單元測(cè)試截珍,也更有利于后期維護(hù)整個(gè)大的state攀甚。因?yàn)樗牟豢勺兲攸c(diǎn),我們不會(huì)在不經(jīng)意見(jiàn)不小心改變了state岗喉,而引起不必要的問(wèn)題秋度。

創(chuàng)建組件的痛點(diǎn)

為了使組件中的css作用域相互獨(dú)立,一般采用Css Module钱床,那么為了使組件看上去更像組件,并且易于后期維護(hù)荚斯,一般我們會(huì)這樣結(jié)構(gòu)化組件文件:

folder.png

那么對(duì)于每一個(gè)初始的jsx,我們大多會(huì)這樣初始化

import s from './App.scss'
import{Component} from 'react';//得到組件方法

class App extends Component{
  
  render(){
    return (
      <div className={s.container}>
      </div>
    )
  } 
}
export default App;


不難發(fā)現(xiàn)查牌,對(duì)于每一個(gè)組件事期,我都需要去手動(dòng)的創(chuàng)建這些文件和文件夾,而這些操作其實(shí)是重復(fù)且無(wú)意義的勞動(dòng)纸颜,于是我造了一個(gè)小輪子兽泣,一個(gè)命令行小工具,來(lái)解決這個(gè)痛點(diǎn)懂衩。
react-component-maker撞叨,歡迎猛戳點(diǎn)star金踪!

結(jié)語(yǔ)

困了,本寶寶要睡覺(jué)了牵敷,還有的內(nèi)容下次再說(shuō)吧胡岔,再見(jiàn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末枷餐,一起剝皮案震驚了整個(gè)濱河市靶瘸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌毛肋,老刑警劉巖怨咪,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異润匙,居然都是意外死亡诗眨,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)孕讳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)匠楚,“玉大人,你說(shuō)我怎么就攤上這事厂财∮蟛荆” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵璃饱,是天一觀(guān)的道長(zhǎng)与斤。 經(jīng)常有香客問(wèn)我,道長(zhǎng)荚恶,這世上最難降的妖魔是什么撩穿? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮裆甩,結(jié)果婚禮上冗锁,老公的妹妹穿的比我還像新娘齐唆。我一直安慰自己嗤栓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布箍邮。 她就那樣靜靜地躺著茉帅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锭弊。 梳的紋絲不亂的頭發(fā)上堪澎,一...
    開(kāi)封第一講書(shū)人閱讀 51,598評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音味滞,去河邊找鬼樱蛤。 笑死钮呀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的昨凡。 我是一名探鬼主播爽醋,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼便脊!你這毒婦竟也來(lái)了蚂四?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤哪痰,失蹤者是張志新(化名)和其女友劉穎遂赠,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體晌杰,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡跷睦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了肋演。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秘噪。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拗秘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蜀踏,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布丘跌,位于F島的核電站眶掌,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏绒瘦。R本人自食惡果不足惜称簿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望惰帽。 院中可真熱鬧憨降,春花似錦、人聲如沸该酗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)呜魄。三九已至悔叽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間爵嗅,已是汗流浹背娇澎。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留睹晒,地道東北人趟庄。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓括细,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親戚啥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子勒极,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容