從零搭建項(xiàng)目(5) --- 前端: 搭建路由和狀態(tài)管理

我的博客地址

正式地址
測試地址
前端源碼
后端源碼

文章目錄

  1. 項(xiàng)目及其技術(shù)棧介紹
  2. 前端: 項(xiàng)目初始化
  3. 前端: 使用Sass和Antd
  4. 前端: 開發(fā)體驗(yàn)優(yōu)化
  5. 前端: 搭建路由和狀態(tài)管理
  6. 前端: 支持Axios
  7. 前端: 打包與環(huán)境變量設(shè)置
  8. 前端: 團(tuán)隊(duì)代碼規(guī)范
  9. 后端: 項(xiàng)目初始化和使用Koa相關(guān)
  10. 后端: 使用TypeORM和MySQL
  11. 部署: 使用nginx部署前端項(xiàng)目
  12. 部署: 后端部署
  13. 部署: 使用jenkins自動(dòng)化部署

前言

該篇博客介紹如何使用react-router4+搭建前端路由,并使用最新的suspense和lazy構(gòu)建路由的按需加載。同時(shí)介紹狀態(tài)管理的搭建,其中在狀態(tài)管理搭建中,會嘗試使用最新的useReducer+context來搭建前端的狀態(tài)管理,以及他與TypeScript之間的配合。

  1. React Router4+,suspense,lazy
  2. useReducer + context

前端路由搭建

  • 安裝react-router
    首先我們需要安裝react-router以及他的類型文件
    npm i -S react-router-dom
    npm i -D @types/react-router-dom
    在這里說一下react-routerreact-router-dom之間的區(qū)別:
    react-routerreact-router-dom的核心代碼,提供理由的核心api,例如Router、Route、Switch等,而react-router-dom提供了BrowserRouter,Link等api,react-router-dom里面包含了react-router,所以一般只需要安裝react-router-dom

  • 編寫路由頁面
    然后我們在src/containers/views中編寫兩個(gè)路由頁面PageAPageB

    image.png

  • 接著我們還是在src/containers/views中新建App組件,并在App組件下新建routerMap.tsx文件用作存放路由表。
    routerMap文件中,我們引入lazy方法,并通過import()引入PageAPageB,然后通過統(tǒng)統(tǒng)放到一個(gè)數(shù)組中,將這個(gè)數(shù)組導(dǎo)出去:

    image.png

  • 我們?nèi)サ?code>App/index.tsx中,從react-router-dom中導(dǎo)入BrowserRouter, Route和Switch,以及從React中導(dǎo)入Suspense組件,然后編寫路由文件,并將其用Suspense包裹起來,使用了lazy方法導(dǎo)入的組件必須用Suspense包裹,否則不能加載出來并報(bào)錯(cuò):

    image.png

  • 在這里需要注意的是,如果使用的是BrowserRouter,需要在webpack中加上devServer配置,并打開historyApiFallback,原因是當(dāng)跳轉(zhuǎn)到page-b頁面的時(shí)候,他會試圖尋找page-b.html,但我們是單頁應(yīng)用,所以沒有這個(gè)文件,從而出現(xiàn)找不到的情況,而historyApiFallback會在找不到頁面的情況下跳轉(zhuǎn)回index.html,避免直接出現(xiàn)找不到的情況:

    image.png

  • 最后我們回到頁面查看跳轉(zhuǎn)情況:
    路徑為/的時(shí)候加載PageA:

    image.png

    當(dāng)路徑切換為/page-b的時(shí)候,則加載PageB:
    image.png

    這時(shí)候我們的前端路由就搭建好了,并且可以進(jìn)行動(dòng)態(tài)加載

  • 使用withRouter方法進(jìn)行路由跳轉(zhuǎn)
    去到PageA頁面添加如下代碼:

    image.png

    image.png

    這時(shí)候點(diǎn)擊跳轉(zhuǎn)B按鈕的時(shí)候就能夠跳轉(zhuǎn)到/page-b路徑了:
    image.png

狀態(tài)管理搭建

在React技術(shù)棧中我們通常使用MobxRedux進(jìn)行前端狀態(tài)管理,但在本項(xiàng)目中未采用這兩個(gè)庫,而是使用了useReducer + context的方式來進(jìn)行搭建,而本文中則使用一個(gè)加減計(jì)數(shù)器的方式來展示如何搭建和使用useReducer + context狀態(tài)管理

進(jìn)行這一步之前首先需要知道如何使用useContextcreateContext以及useReducer

  • 首先我們在src文件夾下新建兩個(gè)文件夾storecomponents,其中store用于存儲共用狀態(tài)和配置,components用于存放組件。

    image.png

  • 然后我們在store文件夾中新建index.tsx文件和count文件夾,在count文件夾中新建index.tsxreducer.ts以及types.d.ts文件:

    image.png

  • 其中index.tsx文件用于存放Provider和初始狀態(tài),如下圖:

    image.png

  • 然后在reducer.ts中,我們開始編寫reducer:

    image.png

    編寫完成在index.tsx中導(dǎo)入:
    image.png

  • 解決類型報(bào)錯(cuò)問題
    這時(shí)候你會發(fā)現(xiàn)reducer和index.tsx中都存在很多報(bào)錯(cuò),這是因?yàn)闆]有添加類型導(dǎo)致ts認(rèn)為他們是any類型,所以我們?yōu)樗麄兲砑宇愋臀募?br> 我們?nèi)サ街靶陆ǖ?code>types.d.ts文件中,定義好state的接口和action的類型,為了避免今后store變得原來越大,我們使用命名空間來避免命名沖突:

    image.png

    之后到reducer.ts將類型補(bǔ)充上去:
    image.png

    index.tsxprops的報(bào)錯(cuò)則可以使用React自帶的ComponentType類型將Provider定義為組件類型以解決:
    image.png

    image.png

  • 定義Context的類型
    另外有些小伙伴可能會有如下ts錯(cuò)誤:

    image.png

    這是因?yàn)槲覀冊?code>createContext中傳入的參數(shù)為null導(dǎo)致的。
    要解決這個(gè)問題首先我們?nèi)サ?code>src/types文件夾中新增context.d.ts文件,接著定義Context的類型,注意因?yàn)橹霸贑ontext的value中我們放入的是statedispatch,所以這兩個(gè)都需要進(jìn)行定義,而state和dispatch每個(gè)store可能都不一樣,所以需要用到泛型:
    image.png

    之后到index.tsx中進(jìn)行使用,注意這里我們從react中導(dǎo)入了Dispatch類型:
    image.png

    最后我們到tsconfig.json中將strictNullChecks的屬性設(shè)置為false:
    image.png

  • 最后我們回到store/index.tsx文件中,導(dǎo)入所有的ProvideruseXXXStore,然后組成一個(gè)數(shù)組,通過一個(gè)總的Provider進(jìn)行導(dǎo)出:

    image.png

    然后到src/index.tsx中導(dǎo)入這個(gè)總的Provider,并使用它包裹<App />組件
    image.png

  • 驗(yàn)證成果
    驗(yàn)證成果之前我們需要先將store和components的路徑別名分別添加進(jìn)webpack和tsconfig中去,不動(dòng)怎么添加的看我上一篇文章:

    image.png

    image.png

我們到之前新建的components文件夾中新建兩個(gè)組件CountOperationShowCount:

image.png

image.png

然后在里面將useTestStore方法從store引入,這個(gè)方法執(zhí)行后可以得到statedispatch
image.png

image.png

并且這些都是帶有類型提示的,說明我們的ts和useReducer + context結(jié)合得非常棒了:
image.png

最后把這兩個(gè)組件在PageA頁面中引入進(jìn)行成果驗(yàn)證:

image.png

查看結(jié)果:
image.png

這樣我們的useReducer + context的狀態(tài)管理方案就完成了。
難點(diǎn)我估計(jì)在于對Context的類型編寫,因?yàn)檫@一塊會用到嵌套的泛型,而泛型在TypeScript中是一個(gè)難點(diǎn),但這個(gè)難點(diǎn)是必須攻克的:

image.png

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,024評論 3 413
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,285評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,548評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,328評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,878評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,098評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,616評論 1 331
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,554評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,725評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,971評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,361評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,613評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,339評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,695評論 2 370

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