老熟女激烈的高潮_日韩一级黄色录像_亚洲1区2区3区视频_精品少妇一区二区三区在线播放_国产欧美日产久久_午夜福利精品导航凹凸

淺談React異步組件的使用方法

本篇內容介紹了“React異步組件的使用方法”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

創新互聯建站長期為千余家客戶提供的網站建設服務,團隊從業經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯網生態環境。為吉安企業提供專業的成都網站設計、做網站,吉安網站改版等技術服務。擁有十載豐富建站經驗和眾多成功案例,為您定制開發。

一 前言

今天我們聊一聊React中的異步組件的現況和未來,異步組件很可能是未來從數據交互到UI展示一種流暢的技術方案,所以既然要吃透React,進階React,就有必要搞懂異步組件。

老規矩,我們還是帶著問題開始今天的思考?(自測掌握程度)

  • 1 什么是React異步組件,解決什么問題?

  • 2 componentDidCatch如何捕獲到渲染階段錯誤,又這么彌補。

  • 3 React.lazy如何實現動態加載的?

  • 4 React.lazy為什么要在Supsonse內部。

  • 5 Supsonse原理是什么?

二 初識:異步組件

1 什么是異步組件

我們先來想想目前的React應用中使用ajax或者fetch進行數據交互場景,基本上就是這樣的,在類組件中componentDidMount和函數組件effect中進行數據交互,得到數據后,再渲染UI視圖。那么可不可以讓組件的渲染等待異步數據請求完畢,得到數據后再進行render呢?

對于上面這種情況,第一感覺是難以置信,如果能夠實現讓渲染中斷,等到數據請求之后,再渲染呢?那就是Susponse,上面說到的不可能實現的事,Susponse做到了,React  16.6 新增了,Susponse 讓組件“等待”某個異步操作,直到該異步操作結束即可渲染。

傳統模式:渲染組件-> 請求數據 -> 再渲染組件。

異步模式:請求數據-> 渲染組件。

2 開啟Suspense模式

一個傳統模式下的數據交互應該是這個樣子的。

function Index(){     const [ userInfo , setUserInfo ] = React.useState(0)     React.useEffect(()=>{        /* 請求數據交互 */        getUserInfo().then(res=>{            setUserInfo(res)        })     },[])     return 
         

{userInfo.name}

;     
 } export default function Home(){     return 
              
 }

流程:頁面初始化掛載,useEffect里面請求數據,通過useState改變數據,二次更新組件渲染數據。

那么如果用Susponse異步模式就可以這么寫:

function FutureAsyncComponent (){     const userInfo = getUserInfo()     return 
         

{userInfo.name}

;      
 }  /* 未來的異步模式 */ export default function Home(){    return 
        loading... 
 } >                      
 }

當數據還沒有加載完成時候,會展示Suspense中 fallback的內容,彌補請求數據中過渡效果 ,盡管這個模式在現在版本中還不能正式使用,但是將來  React 會支持這樣的代碼形式。

三 溯源:從componentDidCatch到Suspense

至于Suspense是如何將上述不可能的事情變成可能的呢?這就要從 componentDidCatch 說起了,在 React 推出 v16  的時候,就增加了一個新生命周期函數 componentDidCatch。如果某個組件定義了  componentDidCatch,那么這個組件中所有的子組件在渲染過程中拋出異常時,這個 componentDidCatch 函數就會被調用。

componentDidCatch使用

componentDidCatch 可以捕獲異常,它接受兩個參數:

1 error —— 拋出的錯誤。

2 info —— 帶有 componentStack key 的對象,其中包含有關組件引發錯誤的棧信息。

我們來模擬一個子組件渲染失敗的情況:

/* 正常組件,可以渲染 */ function Children(){   return 
 hello ,let us learn React 
 }  /* 非React組件,將無法正常渲染 */ function Children1(){   return  } export default class Index extends React.Component{   componentDidCatch(error,info){       console.log(error,info)   }   render(){     return 
                   
   } }

如上,我們模擬一個render失敗的場景,將一個非React組件Children1當作正常的React的組件來渲染,這樣在渲染階段就會報錯,錯誤信息就會被  componentDidCatch捕獲到,錯誤信息如下:

淺談React異步組件的使用方法

對于如上如果在渲染子組件的時候出現錯誤,會導致整個組件渲染失敗,無法顯示,正常的組件Children也會被牽連,這個時候我們需要在componentDidCatch做一些補救措施,比如我們發現  componentDidCatch 失敗,可以給Children1加一個狀態控制,如果渲染失敗,那么終止Children1的render。

function ErroMessage(){   return 
渲染出現錯誤~
 }  export default class Index extends React.Component{   state={ errorRender:false }   componentDidCatch(error,info){       /* 補救措施 */       this.setState({         errorRender:true       })   }   render(){     return 
              { this.state.errorRender ?  :   }     
   } }

淺談React異步組件的使用方法

如果出現錯誤,通過setState重新渲染,并移除失敗的組件,這樣組件就能正常渲染了,同樣也不影響Children掛載。componentDidCatch一方面捕獲在渲染階段出現的錯誤,另一方面可以在生命周期的內部執行副作用去挽回渲染異常帶來的損失。

componentDidCatch原理

componentDidCatch原理應該很好理解,內部可以通過try{}catch(error){}來捕獲渲染錯誤,處理渲染錯誤。

try {   //嘗試渲染子組件 } catch (error) {   // 出現錯誤,componentDidCatch被調用, }

componentDidCatch思想能否遷移到Suspense上

那么回到我們的異步組件上來,如果讓異步的代碼放在同步執行,是肯定不會正常的渲染的,我們還是要先請求數據,等到數據返回,再用返回的數據進行渲染,那么重點在于這個等字,如何讓同步的渲染停止下來,去等異步的數據請求呢?拋出異常可以嗎?  異常可以讓代碼停止執行,當然也可以讓渲染中止。

Suspense 就是用拋出異常的方式中止的渲染,Suspense 需要一個 createFetcher 函數會封裝異步操作,當嘗試從  createFetcher 返回的結果讀取數據時,有兩種可能:一種是數據已經就緒,那就直接返回結果;還有一種可能是異步操作還沒有結束,數據沒有就緒,這時候  createFetcher 會拋出一個“異常”。

這個“異常”是正常的代碼錯誤嗎?非也,這個異常是封裝請求數據的Promise對象,里面是真正的數據請求方法,既然 Suspense  能夠拋出異常,就能夠通過類似 componentDidCatch的try{}catch{}去獲取這個異常。

獲取這個異常之后干什么呢?  我們知道這個異常是Promise,那么接下來當然是執行這個Promise,在成功狀態后,獲取數據,然后再次渲染組件,此時的渲染就已經讀取到正常的數據,那么可以正常的渲染了。接下來我們模擬一下createFetcher和Suspense

我們模擬一個簡單createFetcher

/**  *   * @param {*} fn  我們請求數據交互的函數,返回一個數據請求的Promise   */ function createFetcher(fn){     const fetcher = {         status:'pedding',         result:null,         p:null     }     return function (){       const getDataPromise = fn()       fetcher.p = getDataPromise       getDataPromise.then(result=>{ /* 成功獲取數據 */          fetcher.result = result           fetcher.status = 'resolve'       })          if(fetcher.status === 'pedding'){ /* 第一次執行中斷渲染,第二次 */          throw fetcher       }       /* 第二次執行 */       if(fetcher.status)       return fetcher.result     } }

我們模擬一個簡單的Suspense

export class Suspense extends React.Component{    state={ isRender: true  }    componentDidCatch(e){      /* 異步請求中,渲染 fallback */      this.setState({ isRender:false })      const { p } = e      Promise.resolve(p).then(()=>{        /* 數據請求后,渲染真實組件 */        this.setState({ isRender:true })      })    }    render(){      const { isRender } = this.state      const { children , fallback } = this.props      return isRender ? children : fallback    } }

用 componentDidCatch 捕獲異步請求,如果有異步請求渲染  fallback,等到異步請求執行完畢,渲染真實組件,借此整個異步流程完畢。但為了讓大家明白流程,只是一次模擬異步的過程,實際流程要比這個復雜的多。

流程圖:

淺談React異步組件的使用方法

四 實踐:從Suspense到React.lazy

React.lazy簡介

Suspense帶來的異步組件的革命還沒有一個實質性的成果,目前版本沒有正式投入使用,但是React.lazy是目前版本Suspense的最佳實踐。我們都知道React.lazy配合Suspense可以實現懶加載,按需加載,這樣很利于代碼分割,不會讓初始化的時候加載大量的文件,減少首屏時間。

React.lazy基本使用

const LazyComponent = React.lazy(()=>import('./text'))

React.lazy接受一個函數,這個函數需要動態調用 import()。它必須返回一個 Promise ,該 Promise需要 resolve 一個  default export 的 React 組件。

我們先來看一下基本使用:

const LazyComponent = React.lazy(() => import('./test.js'))  export default function Index(){    return loading...
} >             }

我們用Promise模擬一下 import()效果,將如上 LazyComponent改成如下的樣子:

function Test(){   return 《React進階實踐指南》即將上線~
 } const LazyComponent =  React.lazy(()=> new Promise((resolve)=>{   setTimeout(()=>{       resolve({           default: ()=>        })   },2000) }))

效果:

淺談React異步組件的使用方法

React.lazy原理解讀

React.lazy 是如何配合Susponse  實現動態加載的效果的呢?實際上,lazy內部就是做了一個createFetcher,而上面講到createFetcher得到渲染的數據,而lazy里面自帶的createFetcher異步請求的是組件。lazy內部模擬一個promiseA規范場景。我們完全可以理解React.lazy用Promise模擬了一個請求數據的過程,但是請求的結果不是數據,而是一個動態的組件。

接下來我們看一下lazy是如何處理的

function lazy(ctor){     return {          $$typeof: REACT_LAZY_TYPE,          _payload:{             _status: -1,  //初始化狀態             _result: ctor,          },          _init:function(payload){              if(payload._status===-1){ /* 第一次執行會走這里  */                 const ctor = payload._result;                 const thenable = ctor();                 payload._status = Pending;                 payload._result = thenable;                 thenable.then((moduleObject)=>{                     const defaultExport = moduleObject.default;                     resolved._status = Resolved; // 1 成功狀態                     resolved._result = defaultExport;/* defaultExport 為我們動態加載的組件本身  */                  })              }             if(payload._status === Resolved){ // 成功狀態                 return payload._result;             }             else {  //第一次會拋出Promise異常給Suspense                 throw payload._result;              }          }     } }

React.lazy包裹的組件會標記REACT_LAZY_TYPE類型的element,在調和階段會變成 LazyComponent  類型的fiber,React對LazyComponent會有單獨的處理邏輯,第一次渲染首先會執行 _init  方法。此時這個_init方法就可以理解成createFetcher。

我們看一下lazy中init函數的執行:

react-reconciler/src/ReactFiberBeginWork.js

function mountLazyComponent(){     const init = lazyComponent._init;     let Component = init(payload); }

流程圖

淺談React異步組件的使用方法

五 展望:Suspense未來可期

你當下并不使用 Relay,那么你暫時無法在應用中試用 Suspense。因為迄今為止,在實現了 Suspense 的庫中,Relay  是我們唯一在生產環境測試過,且對它的運作有把握的一個庫。

目前Suspense還并不能,如果你想使用,可以嘗試一下在生產環境使用集成了 Suspense 的 Relay。Relay 指南!

Suspense能解決什么?

Suspense面臨挑戰?

對于未來的Suspense能否作為主流異步請求數據渲染的方案,筆者認為Suspense未來還是充滿期待,那么對于Suspense的挑戰,個人感覺在于以下幾個方面:

1  concurrent模式下的Susponse可以帶來更好的用戶體驗,react團隊能夠讓未來的Suspense更靈活,有一套更清晰明確的createFetcher制作手冊,是未來的concurrent模式下Suspense脫穎而出的關鍵。

2 Suspense能否廣泛使用,更在于 Suspense 的生態發展,有一個穩定的數據請求庫與Suspense完美契合。

3  開發者對Suspense的價值的認可,如果Suspense在未來的表現力更出色的話,會有更多開發者寧愿自己封裝一套數據請求方法,給優秀的Suspense買單。

“React異步組件的使用方法”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注創新互聯網站,小編將為大家輸出更多高質量的實用文章!


標題名稱:淺談React異步組件的使用方法
文章位置:http://www.xueling.net.cn/article/gooded.html

其他資訊

在線咨詢
服務熱線
服務熱線:028-86922220
TOP
主站蜘蛛池模板: 久草在线视频看看 | 国产性天天综合网 | 九九99靖品免费 | 精品福利视频一区二区三区 | 日日干夜夜操高清视频 | 浪荡女天天不停挨CAO日常视频 | 大香伊蕉最新视频 | 日韩成人av在线 | 熟女人妻aⅴ一区二区三区60路 | 天堂网www天堂网最新版 | 国产精品亚洲第一区二区三区 | 国精产品一区一区三区免费视频 | 性色AV无码久久一区二区三区 | 在线观看国产v片 | 国产SM调教视频在线观看 | 日本大片免a费观看视频 | 国产农村寡妇一级毛片 | 成人爽a毛片在线视频淮北 成人免费观看视频大全 | 97国产在线看片免费人成视频 | 国产成人啪精品视频免费视频 | 一区二区三区四区五区精品 | 日韩艹逼| 精品人妻中文字幕无码蜜桃臀 | 乱人伦人妻中文字幕无码久久网 | 日本爆乳片手机在线播放 | 一级毛片久久久 | 天天天天天干 | 99久久精品无码一区二区毛片免费 | 在线观看免费视频一区 | youjizz丰满熟妇 | 日韩高清在线一区二区 | 国产一起草 | 日本少妇三级HD激情在线观看 | 啦啦啦在线观看视频免费观看 | 国产真实强奷系列在线观看 | 国产精品盗摄!偷窥盗摄 | 欧美1区视频 | 少妇裸体淫交视频免观看 | 波多野结衣一区二区三区中文字幕 | 亚洲日韩精品A∨片无码加勒比 | 免费观看老乱熟视频 |