日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
在React中使用Context的兩點注意事項

  [[419686]]

成都創(chuàng)新互聯(lián)是一家專業(yè)提供龍陵企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、H5頁面制作、小程序制作等業(yè)務(wù)。10年已為龍陵眾多企業(yè)、政府機構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站制作公司優(yōu)惠進行中。

Context是個好東西,先不論代數(shù)效應(yīng)之類純理論的概念,能在組件樹上無視深度地透傳狀態(tài)確實能給開發(fā)帶來很大的便利。

但如果Context的使用上不注意一些細節(jié),使用不當,對應(yīng)用的性能是有可能造成災(zāi)難性影響的。近期在做一個產(chǎn)品的性能優(yōu)化的時候,總結(jié)出來微不足道的兩點“常識”。

關(guān)于順序

先來看一張圖,我愿稱之為世界名畫: 

這就一演示的界面,沒什么東西,我的邏輯也很簡單:

 
 
 
 
  1. import React, {memo, useReducer} from 'react'; 
  2. import {ConfigProvider, Tooltip} from 'antd'; 
  3. import ZH_CN from 'antd/lib/locale-provider/zh_CN'; 
  4. import 'antd/dist/antd.min.css'; 
  5.  
  6. const Text = ({text}) => { 
  7.     return ( 
  8.          
  9.             
    {text}
     
  10.          
  11.     ); 
  12. }; 
  13.  
  14. const MemoedText = memo(Text); 
  15.  
  16. const ConfigProviderInside = () => { 
  17.     const [counter, inc] = useReducer((v) => v + 1, 1); 
  18.  
  19.     return ( 
  20.          
  21.             
     
  22.                  
  23.                 
    App Counter: {counter}
     
  24.                  
  25.                     FORCE UPDATE 
  26.                  
  27.             
 
  •          
  •     ); 
  • }; 
  • 點一下按鈕,整個界面都更新了一遍,是不是也還算正常?那如果做一下“簡單”地優(yōu)化呢: 

    是不是很酸爽?我干了什么呢:

     
     
     
     
    1. const ConfigProviderOutside = () => { 
    2.     const [counter, inc] = useReducer((v) => v + 1, 1); 
    3.  
    4.     return ( 
    5.         
       
    6.              
    7.             
      App Counter: {counter}
       
    8.              
    9.                 FORCE UPDATE 
    10.              
    11.         
     
  •     ); 
  • }; 
  •  
  • render( 
  •      
  •          
  •      
  • ); 
  • 我把antd的ConfigProvider放到了外面,就這一行代碼。

    原因也很簡單,antd的ConfigProvider并沒有做什么優(yōu)化,它每一次給Context的value都是一個全新的對象(雖然內(nèi)容并沒有變化),這就會導(dǎo)致所有關(guān)聯(lián)的組件都觸發(fā)更新(雖然毫無意義)。這在你的系統(tǒng)中的下場就是你拼合地用memo、PureComponent之類的方法優(yōu)化自己寫的組件,但那里面的antd組件們卻歡快地渲染到停不下來。

    所以第一條經(jīng)驗是:好 好梳理Context的上下關(guān)系,把那些理論上不會變的放到最外面,把頻繁會變的往里放。

    什么是不會變的呢,比如Locale、Constant,以及一些系統(tǒng)級的做依賴注入的,這些往往整個生命周期都不會變。

    然后是類似CurrentUser這樣系統(tǒng)啟動的時候請求一次數(shù)據(jù)的,會從null變成固定的值,隨后就不會變了,這一類也盡量往外放。

    最后像是Router這樣的,會頻繁變化的,要放到最里面,免得因為它的更新把其它不怎么變的Context也帶進去。

    關(guān)于粒度

    來看一個非常經(jīng)典的Context:

     
     
     
     
    1. const DEFAULT_VALUE = { 
    2.     props: null, 
    3.     openGlobalModal: () => undefined, 
    4.     closeGlobalModal: () => undefined, 
    5. }; 
    6.  
    7. const GlobalModalContext = createContext(DEFAULT_VALUE); 
    8.  
    9. const GlobalModalContextProvider = ({children}) => { 
    10.     const [props, setProps] = useState(null); 
    11.     const closeGlobalModal = useCallback( 
    12.         () => setProps(null), 
    13.         [] 
    14.     ); 
    15.     const contextValue = useMemo( 
    16.         () => { 
    17.             return { 
    18.                 props, 
    19.                 closeGlobalModal, 
    20.                 openGlobalModal: setProps, 
    21.             }; 
    22.         }, 
    23.         [props, closeGlobalModal, setProps] 
    24.     ); 
    25.      
    26.     return ( 
    27.          
    28.             {children} 
    29.          
    30.     ); 
    31. }; 

    用一個Context來統(tǒng)一地管理全局單例的對話框,也是一種比較常見的玩法。如果你這么用:

     
     
     
     
    1. const EditUserLabel = ({id}) => { 
    2.     const {openGlobalModal} = useContext(GlobalMoadlContext); 
    3.     const edit = useCallback( 
    4.         () => openGlobalModal({title: '編輯用戶', children: }), 
    5.         [openGlobalModal, id] 
    6.     ); 
    7.  
    8.     return 編輯; 
    9. }; 
    10.  
    11. const columns = [ 
    12.     // ... 
    13.     { 
    14.         title: '操作', 
    15.         key: 'action', 
    16.         dataIndex: 'id' 
    17.         render: id => 
    18.     } 
    19.  
    20. const UserList = ({dataSource}) => ( 
    21.      
    22. ); 

    在一個表格里每一行放一個“編輯”標簽,然后在全局放一個對話框:

     
     
     
     
    1. const GlobalModal = () => { 
    2.     const {props} = useContext(GlobalMoadlContext); 
    3.      
    4.     return !!props && 
    5. }; 

    你就會驚訝地發(fā)現(xiàn), 每當你編輯一個用戶(或在其它地方觸發(fā)對話框),表格中每一行的編輯標簽都會更新。

    原因很容易分析, 因為當你打開對話框的時候,props是變化的,因而contextValue也變化了,所以雖然編輯標簽只用了openGlobalModal這個永遠不會變的東西,卻也硬生生被帶著渲染了起來。

    如果想追求更少地渲染,就要關(guān)注第二條經(jīng)驗: 一個Context中的東西往往并不一起被使用,將它們按使用場景分開,特別是要將多變的和不變的分開。

    像上面的代碼,就可以優(yōu)化成這樣:

     
     
     
     
    1. const GlobalModalPropsContext = createContext(null); 
    2.  
    3. const DEFAULT_ACTION = { 
    4.     openGlobalModal: () => undefined, 
    5.     closeGlobalModal: () => undefined, 
    6. }; 
    7.  
    8. const GlobalModalActionContext = createContext(DEFAULT_ACTION); 
    9.  
    10. const GlobalModalContextProvider = ({children}) => { 
    11.     const [props, setProps] = useState(null); 
    12.     const closeGlobalModal = useCallback( 
    13.         () => setProps(null), 
    14.         [] 
    15.     ); 
    16.     const actionValue = useMemo( 
    17.         () => { 
    18.             return { 
    19.                 closeGlobalModal, 
    20.                 openGlobalModal: setProps, 
    21.             }; 
    22.         }, 
    23.         [closeGlobalModal, setProps] 
    24.     ); 
    25.      
    26.     return ( 
    27.         // 注意第一條經(jīng)驗,變得少的在外面 
    28.          
    29.              
    30.                 {children} 
    31.              
    32.          
    33.     ); 
    34. }; 

    只要根據(jù)實際的需要,去訪問2個不同的Context,就可以做到最優(yōu)化的屬性粒度和最少的渲染。

    當然我也建議不要直接暴露Context本身,而是將它按照使用場景暴露成若干個hook,這樣你可以在一開始不做特別的優(yōu)化,當性能出現(xiàn)瓶頸的時候再拆Context,只需要修改hook的實現(xiàn)就能做到對外的兼容。

    總結(jié)

    1. 關(guān)注在應(yīng)用中使用的Context的順序,讓不變的在外層,多變的在內(nèi)層。
    2. Context中的內(nèi)容可以按使用場景和變與不變來拆分成多個更細粒度匠,以減少渲染。

    網(wǎng)頁名稱:在React中使用Context的兩點注意事項
    鏈接URL:http://m.5511xx.com/article/dhegiec.html