<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        React性能優化系列之減少props改變的實現方法

        來源:懂視網 責編:小采 時間:2020-11-27 22:02:02
        文檔

        React性能優化系列之減少props改變的實現方法

        React性能優化系列之減少props改變的實現方法:React性能優化的一個核心點就是減少render的次數。如果你的組件沒有做過特殊的處理(SCU -- shouldComponentUpdate或使用PureComponent),那每次父組件render時,子組件就會跟著一起被重新渲染。通常一個復雜的子組件都會進行一些優化,比如:SCU 使用P
        推薦度:
        導讀React性能優化系列之減少props改變的實現方法:React性能優化的一個核心點就是減少render的次數。如果你的組件沒有做過特殊的處理(SCU -- shouldComponentUpdate或使用PureComponent),那每次父組件render時,子組件就會跟著一起被重新渲染。通常一個復雜的子組件都會進行一些優化,比如:SCU 使用P

        React性能優化的一個核心點就是減少render的次數。如果你的組件沒有做過特殊的處理(SCU -- shouldComponentUpdate或使用PureComponent),那每次父組件render時,子組件就會跟著一起被重新渲染。通常一個復雜的子組件都會進行一些優化,比如:SCU 使用PureComponent組件。對于SCU基本上進行的也都是淺比較,深比較的代價太高。

        對于這些被優化的子組件,我們要減少一些不必要的props改變:比如事件綁定。對于那些依賴于配置項的組件,我們更是減少這些作為props的配置的變化,因為可能一但配置項發生了變化,整個組件都會跟著重新渲染,所以我們要盡可能的減少props的改變

        事件綁定

        class ClickMe extends React.Component {
         state = {
         value: '3333',
         };
        
         render() {
         return (
         <Button
         onClick={() => {
         console.log('l am clicked!', this.state.value);
         }}
         >
         click me
         </Button>
         )
         }
        }
        
        

        相信大多數的開發者React都會指出這種寫法的缺點:每次ClickMe組件渲染的時候onClick屬性與上一次的值相比都是一個不同的匿名函數,如果Button是一個復雜的子組件且內部沒有經過任何特殊的處理,那就會造成多余的渲染。對于這種情況的做法一般有兩種方式:

        1. 在構造函數內綁定 this
        2. 將箭頭函數賦予class的屬性
        class ClickMe extends React.Component {
         state = {
         value: '3333',
         };
        
         handleClick = () => {
         console.log('l am clicked!', this.state.value);
         };
        
         render() {
         return (
         <Button
         onClick={this.handleClick}
         >
         click me
         </Button>
         )
         }
        }
        
        // 或
        class ClickMe extends React.Component {
         constuctor(props) {
         super(props);
         this.state = {
         value: '3333',
         };
         this.handleClick = this.handleClick.bind(this);
         }
        
         handleClick() {
         console.log('l am clicked!', this.state.value);
         }
        
         render() {
         return (
         <Button
         onClick={this.handleClick}
         >
         click me
         </Button>
         )
         }
        }
        
        

        批量事件綁定

        那在考慮下面這種情況,涉及到子組件的批量綁定時:

        class MultiClick extends React.Component {
         dataSource = [
         { key: '1', value: '1' },
         { key: '2', value: '2' },
         { key: '3', value: '3' },
         { key: '4', value: '4' },
         ];
        
         handleClick = key => {
         console.error('key:', key);
         };
        
         render() {
         return (
         <div>
         {this.dataSource.map(item => (
         <div
         key={item.key}
         onClick={() => {
         this.handleClick(item.key);
         }}
         >
         {item.value}
         </div>
         ))}
         </div>
         );
         }
        }

        類似于這種需要傳遞參數的情況,該如何去優化?

        這個就需要我們去做數據的緩存,即回調的緩存,上述例子如下:

        cacheMap = {};
        
        genClickHandler = key => {
         if (!this.cacheMap[key]) {
         this.cacheMap[key] = () => {
         console.error('key:', key);
         };
         }
         return this.cacheMap[key];
        };
        
        // 綁定
        <div key={item.key} onClick={this.genClickHandler(item.key)}>
         {item.value}
        </div>;
        
        

        如果多個基本類型的參數可以,將他們拼接成字符串作為cacheMap的key,簡單的引用類型可以使用JSON.stringify,不過原則上作為事件綁定的函數 傳遞的參數簡單為好。

        作為配置的props緩存

        說到數據的緩存,不管光是事件的回調,還有很多 其他情況。比如表格的 columns需要根據屬性變化的這種場景:

        class TableDemo extends React.Component {
         getColumns = () => {
         const { name } = this.state;
         return [
         {
         key: '1',
         title: `${name}_1`,
         },
         {
         key: '2',
         title: `${name}_2`,
         },
         ];
         };
        
         render() {
         const { dataSource } = this.props;
         return <Table dataSource={dataSource} columns={this.getColumns()} />;
         }
        }
        
        

        這種情況每次組件render的時候,getColumns都會被調用一次,而這個函數每次的返回值都是不一樣的 ,及時這兩次的name值都相等,原因大家可以類比[] !== []這里就不過多敘述了。

        有一種做法是,將columns作為一個this.state的一個屬性,在初始化和每次 this.state.name改變的時候同步改變this.state.columns的值,但如果有多個 類似于this.state.name的變量控制this.state.columns的值時候,發現每個變量變化的時候都要調用生成columns的方法, 十分的煩瑣易造成錯誤。

        使用緩存可以很好的解決這個問題,在參數較為復雜的時候,我們選擇只緩存上一次的值。先看代碼再說:

        首先我們寫一個緩存的函數

        function cacheFun(cb) {
         let preResult = null
         let preParams = null
         const equalCb = cb || shallowEqual
         return (fun, params) => {
         if (preResult && equalCb(preParams, params)) {
         return preResult
         }
         preResult = fun(params)
         preParams = params
         return preResult
         }
        }

        這個緩存函數是一個閉包函數,保存了上一次的參數和上一次的結果,主要的實現就是比較兩次的參數,相同則返回上一次結果,不同則返回 調用函數的新結果。當然 對于某些特殊的情況只需要根據傳入特定的某幾個參數做出判斷,這種情況你可以傳入自定義的比較函數。先看一下上面的實現:

        cacheFun函數第一個參數為選填的選項,是你比較兩次參數的 方法,如果你不傳入則僅進行 淺比較(與 React 的淺比較相似)。

        返回函數的第一個參數為你的 生成columns的回調,params 為你需要的 變量,如果你的變量比較多,你可以將他們 作為一個對象傳入;那么代碼就類似如下:

        const params = { name, time, handler };
        cacheFun(this.getColumns, params, cb);

        在類中的使用為:

        class TableDemo extends React.Component {
         getColumns = name => {
         return [
         {
         key: '1',
         title: `${name}_1`,
         },
         {
         key: '2',
         title: `${name}_2`,
         },
         ];
         };
        
         getColumnsWrapper = () => {
         const { name } = this.state;
         return cacheFun()(this.getColumns, name);
         };
        
         render() {
         const { dataSource } = this.props;
         return (
         <Table dataSource={dataSource} columns={this.getColumnsWrapper()} />
         );
         }
        }
        

        假如你不喜歡對象的傳值方式,那你可以 對這個緩存函數進行更改:

        function cacheFun(cb) {
         let preResult = null;
         let preParams = null;
         const equalCb = cb || shallowEqual;
         return (fun, ...params) => {
         if (preResult) {
         const isEqual = params.ervey((param, i) => {
         const preParam = preParams && preParams[i];
         return equalCb(param, preParam);
         });
         if (isEqual) {
         return preResult;
         }
         }
         preResult = fun(params);
         preParams = params;
         return preResult;
         };
        }
        

        你這可以這樣使用:

        cacheFun()(this.getColumns, name, key, param1, params2);
        // 或者
        cacheFun()(this.getColumns, name, key, { param1, params2 });
        

        這樣配置也就被緩存優化了,當TableDemo組件因非name屬性render時,這時候你的columns還是返回上一次緩存的值,是的Table這個組件減少了一次因columns引用不同產生的render。如果Table的dataSource數據量很大,那這次對應用的優化就很可觀了。

        數據的緩存

        數據的緩存在原生的內部也有使用cacheFun的場景,如對于一個list 根據 searchStr模糊過濾對于的subList

        大致代碼如下:

        class SearchList extends React.Component {
         
         state = {
         list: [
         { value: '1', key: '1' },
         { value: '11', key: '11' },
         { value: '111', key: '111' },
         { value: '2', key: '2' },
         { value: '22', key: '22' },
         { value: '222', key: '222' },
         { value: '2222', key: '2222' },
         ],
         searchStr: '',
         }
        
         // ...
        
         render() {
         const { searchStr, list } = this.state
         const dataSource = list.filter(it => it.indexOf(searchStr) > -1)
         return (
         <div>
         <Input onChange={this.handleChange} />
         <List dataSource={dataSource} />
         </div>
         )
         }
        }
        
        

        對于此情景的優化使用cacheFun也可以實現

        const dataSource = cacheFun()((plist, pSearchStr) => {
         return plist.filter(it => it.indexOf(pSearchStr) > -1)
        }, list, searchStr)
        

        但是有大量的類似于此的衍生值的時候,這樣的寫法又顯得不夠。社區上出現了許多框架如配合react-redux使用reselect(當然也可以單獨使用,不過配合redux使用簡直就是前端數據管理的一大殺手锏),還有mobx的衍生概念等。這些后續會單獨介紹,這里就稍微提一下。

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        React性能優化系列之減少props改變的實現方法

        React性能優化系列之減少props改變的實現方法:React性能優化的一個核心點就是減少render的次數。如果你的組件沒有做過特殊的處理(SCU -- shouldComponentUpdate或使用PureComponent),那每次父組件render時,子組件就會跟著一起被重新渲染。通常一個復雜的子組件都會進行一些優化,比如:SCU 使用P
        推薦度:
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 四虎国产精品免费久久| 67194在线午夜亚洲| 久久夜色精品国产噜噜亚洲AV| 一本天堂ⅴ无码亚洲道久久| 免费A级毛片无码视频| 亚洲人成网站18禁止一区| 亚洲一区无码中文字幕乱码| 131美女爱做免费毛片| 亚洲不卡中文字幕无码| 五月天国产成人AV免费观看| 免费视频中文字幕| 亚洲国产日韩在线人成下载| 国产1024精品视频专区免费| 免费人妻精品一区二区三区| 亚洲A丁香五香天堂网| 免费国产黄网站在线看 | 久久青青草原亚洲av无码app| 国产精品美女午夜爽爽爽免费| 亚洲成av人片在线看片| 最近免费中文字幕大全免费| 亚洲欧洲日产国码二区首页| 亚洲精品无码日韩国产不卡?V| 国产在线观看麻豆91精品免费| 亚洲中文无码线在线观看| 久久国产成人精品国产成人亚洲| 在线播放国产不卡免费视频| 亚洲男女性高爱潮网站| 在线观看免费精品国产| 午夜在线免费视频| 亚洲日本一线产区和二线产区对比| 在线视频免费观看www动漫| 污网站在线免费观看| 香蕉大伊亚洲人在线观看| 国产色爽免费视频| 国产精品美女免费视频观看| 国产gv天堂亚洲国产gv刚刚碰| AAA日本高清在线播放免费观看| 少妇中文字幕乱码亚洲影视| 久久久久久亚洲精品不卡| 日本特黄特黄刺激大片免费| 无码日韩人妻av一区免费|