<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          我?guī)鸵慌笥阎貥嬃它c代碼,他直呼牛批,但基操勿六

          共 4083字,需瀏覽 9分鐘

           ·

          2022-04-20 23:02

          首先事情是這樣的

          我一朋友,用 react 開發(fā)前端時間不長,一些簡單的功能和頁面沒啥大問題。前不久React 18 發(fā)布了,他就用 create-react-app 創(chuàng)建了一個新項目,合計練練手,但誰成想遇到了種種問題,讓我?guī)涂纯矗谑蔷陀辛私酉聛硪牡囊恍┛此坪唵危菍π率謪s很絆腳的小問題。

          react都 18 了,但為啥還是 ReactDom.render

          create-react-app新創(chuàng)建的項目,還是用的ReactDom.render,如下:

          import?React?from?'react'
          import?ReactDOM?from?'react-dom'?//《----------react?17使用的ReactDOM
          import?App?from?'./App'
          import?'./index.css'

          ReactDOM.render(
          ??<React.StrictMode>
          ????<App?/>
          ??React.StrictMode>
          ,
          ??document.getElementById('root')
          )

          ?

          語義大體上:ReactDOMrender 函數,把 JSX Elements 組件,渲染到 id 為'root'的 dom 節(jié)點上。

          ?

          那么用react 18的新寫法改造一下

          ?

          react 18改了

          ?
          //index.tsx
          import?React?from?'react'
          import?{?createRoot?}?from?'react-dom/client'?//《----------react?18使用的ReactDOM/client中的createRoot
          import?App?from?'./App'
          import?'./index.css'

          function?render()?{
          ??const?root?=?createRoot(document.getElementById('root')!)
          ??root.render(
          ????<React.StrictMode>
          ??????<App?/>
          ????React.StrictMode>

          ??)
          }

          ?

          語義大體上:react-dom/clientcreateRoot 函數,把 id 為'root'的 dom 節(jié)點做成了一個渲染器,然后用Render函數把JSX Elements渲染出來。

          ?

          react 都 18 了,React-router 得 v6 啊,但變化好大,咋用啊?

          ?

          React-router v6可謂是變化著實不小,之前v5組織路由是這樣的:

          ?

          React-router v5

          //app.tsx
          import?React?from?'react'
          import?{?BrowserRouter?as?Router,?Route,?Switch?}?from?"react-router-dom";
          export?default?()?=>?{
          ??return?(
          ??????<Router>
          ????????<Switch>
          ??????????<Route?path="/"?component={Login}?/>
          ??????????<Route?path="/pageCenter"?component={PageCenter}?/>
          ????????Switch>

          ??????Router>
          ????)
          ??}
          )

          ?

          PageCenter就是我們的頁面組件,一般都會在這里實現嵌套路由,如:

          ?
          //PageCenter.tsx
          import?React?from?'react'
          import?NestRoute?from?‘./nestRoute’
          import?{?Route,?Switch?}?from?"react-router-dom";
          export?default?()?=>?{
          ??return?(
          ??????<>
          ????????<Switch>
          ??????????<Route?path="/pageCenter/nestRoute"?component={NestRoute}?/>
          ????????Switch>

          ??????<>
          ????)
          ??}
          )

          ?

          em ~~~,跟 app.tsx 中實現的頂層路由很像,一脈相承。

          ?

          評價一波 v5 路由的組織方式吧

          • tsx 文件大臃腫:每配置一個路由,就寫一個 Route 組件,我個人是不喜歡的,我不希望我的 tsx 的代碼太多,這是我的喜好,為了閱讀起來容易,清晰。
          • 項目的文件夾結構復雜嵌套:「頂層路由和嵌套子路由配置分離」,直接影響了工程項目中對項目的文件夾結構的編排。因為不能夠很直接理清頁面組件間的組織關系,不理清會很混亂,維護難度加大,所以理清關系就落在了項目的文件夾結構設計了,這就會導致項目的文件夾結構隨著v5 路由的組織方式的復雜而復雜。

          React-router v6

          可能是因為 v5 的種種原因,才導致 v6 的變化那么大,最突出便是:

          • 「v6 痛快的推出了配置式路由」:一個簡單的配置對象,充分描述出了路由的樣子和組織關系,痛快~~~。
          • 「簡潔的路由嵌套方式」:僅僅在配置了嵌套路由組件中,使用新推出的標簽就搞定了,優(yōu)雅~~~。

          不過~~~,也有一些破壞性的改變,讓我措手不及,比如:

          • 「路由攔截無了!!!」:攔截啊可是,怎么沒有了,這。。。
          • withRouter無了!!!」:函數組件我能用hook搞搞,類組件咋辦,這。。。

          em ~~~沒事 repect,畢竟進步嘛,怎么會沒代價呢,沒有咱就自己搞被,不坐車就不會走了么?

          我為此寫了一個庫r6helper[1],盡可能的彌補了升級 v6 帶來的影響

          • 攔截,安排上了。

          • withRouter,安排上了。

          路由好了,那么路由懶加載得有吧,怎么搞?

          方式還是依然是通過 React.lazy配合import的動態(tài)引入,代碼如下。

          const?Login?=?React.lazy(()?=>?import('./login'))

          然后還要在通過React.Suspense包裹一下這個懶加載組件,否則的話會報錯,這個問題我的那個朋友可是卡住了很久。。。,原因就是忘記了要在懶加載組件外包裹一層React.Suspense

          ...</>}>{>}</React.Suspense>

          但是,朋友又跟我講,每加一個頁面,就寫個lazy引入組件和Suspense包裹,那么頁面一多,代碼就會變成這樣:

          const?PageCenter?=?React.lazy(()?=>?import('./pages/pageCenter'))
          const?Page1?=?React.lazy(()?=>?import('./pages/page1'))
          ...
          export?default?()?=>?{
          ??return?useRoutes([
          ????{
          ??????path:?'/pageCenter',
          ??????children:?[
          ????????{
          ??????????path:?'/page1',
          ??????????element:?<React.Suspense?fallback={<>...}>{}</React.Suspense>
          ????????},
          ??????]
          ????}

          ??])
          }

          嵌套路由

          ????//PageCenter.tsx
          ????import?React?from?'react'
          ????export?default?()?=>?{
          ??????return?(
          ??????????<div>
          ??????????????<Outlet?/>
          ??????????div>

          ????????)
          ??????}
          ????)

          這樣看起來就非常的冗余,很多重復的代碼,希望我能幫他優(yōu)化一下,em ~~~沒問題,開整。

          優(yōu)化代碼

          主要從兩個方面入手:

          • 組件lazy引入上
          • 然后Suspense包裹上

          統(tǒng)一入口

          首先頁面組件都放在了pages路徑下,然后再定向導入,我們加個indexpages文件夾下,進行統(tǒng)一管理。

          //?文件:pages/index.ts
          export?Login?=?React.lazy(()?=>?import('./pages/login'))
          export?Page1?=?React.lazy(()?=>?import('./pages/page1'))

          然后我們重構一下之前的引入代碼:

          const?{?Login,?Page1?}?from?'./pages'

          封裝包裝組件,支持多類型

          寫一個能夠包裝多類型的組件,都可以包裝:

          • 「組件」,包括:「函數組件」「類組件」
          • 「lazy 組件」
          • 「jsx element」

          那么代碼如下:

          //?加載異步組件的loading
          type?ChildT?=?React.LazyExoticComponent<()?=>?JSX.Element>?|?React.FC
          export?const?wrapper?=?(Child:?ChildT,?cutonFallBack?:?CutonFallBackT)?=>?{
          ??//?判斷jsx
          ??if?(Child.type?&&?!Child._init?&&?!Child._payload)?{
          ????return?Child
          ??}?else?{
          ????//?判斷是否為clas和function組件
          ????if?(typeof?Child?===?'function')?{
          ??????return?<Child>Child>
          ????}?else?{
          ??????//?判斷是否為lazy組件
          ??????return?(
          ????????<React.Suspense?fallback={cutonFallBack?||?<>...}>
          ??????????{</Child>}
          ????????React.Suspense>
          ??????)
          ????}
          ??}
          }

          那么這樣整體重構后的代碼,就大體變成了

          const?{?Login,PageCenter,?Page1?}?from?'./pages'
          ...
          export?default?()?=>?{
          ??return?useRoutes([
          ????{
          ??????path:?'/',
          ??????element:wrapper(Login),
          ????},
          ????{
          ??????path:?'/pageCenter',
          ??????children:?[
          ????????{
          ??????????path:?'/page1',
          ??????????element:?wrapper(Page1)
          ????????},
          ????????
          ????{
          ??????path:?'/404',
          ??????element:?wrapper(<div>not?founddiv>)
          ????},
          ??])
          }

          em ~~~樸實無華,但是代碼看起來舒服不少,朋友感嘆學到不少干貨,我感覺這就是基本操作,233333。

          原文

          https://juejin.cn/post/7085674288933502984
          瀏覽 51
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  看老女人操逼 | 国产成人黄色网 | 99热最新国产 | 久久青青草大香蕉手机视频在线 | 爱爱小视频网站 |