• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題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關(guān)鍵字專題關(guān)鍵字專題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
    當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

    React性能優(yōu)化系列之減少props改變的實現(xiàn)方法

    來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-27 22:02:02
    文檔

    React性能優(yōu)化系列之減少props改變的實現(xiàn)方法

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

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

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

    事件綁定

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

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

    1. 在構(gòu)造函數(shù)內(nèi)綁定 this
    2. 將箭頭函數(shù)賦予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>
     );
     }
    }

    類似于這種需要傳遞參數(shù)的情況,該如何去優(yōu)化?

    這個就需要我們?nèi)プ鰯?shù)據(jù)的緩存,即回調(diào)的緩存,上述例子如下:

    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>;
    
    

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

    作為配置的props緩存

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

    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都會被調(diào)用一次,而這個函數(shù)每次的返回值都是不一樣的 ,及時這兩次的name值都相等,原因大家可以類比[] !== []這里就不過多敘述了。

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

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

    首先我們寫一個緩存的函數(shù)

    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
     }
    }

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

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

    返回函數(shù)的第一個參數(shù)為你的 生成columns的回調(diào),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()} />
     );
     }
    }
    

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

    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 });
    

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

    數(shù)據(jù)的緩存

    數(shù)據(jù)的緩存在原生的內(nèi)部也有使用cacheFun的場景,如對于一個list 根據(jù) 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>
     )
     }
    }
    
    

    對于此情景的優(yōu)化使用cacheFun也可以實現(xiàn)

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

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

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

    文檔

    React性能優(yōu)化系列之減少props改變的實現(xiàn)方法

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

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 99re8这里有精品热视频免费| 欧美亚洲国产成人精品| 91探花福利精品国产自产在线 | 国产高清在线精品一区二区 | 曰韩精品无码一区二区三区| 国产精品嫩草影院一二三区| 精品国产一区二区三区久久| 久久久久99精品成人片试看| 亚洲国产精品尤物YW在线观看| 国自产精品手机在线观看视频| 久热这里只精品99re8久| 精品不卡一区二区| 亚洲人精品午夜射精日韩| 精品久久久久久国产免费了| 2021国产三级精品三级在专区 | 久久99国产乱子伦精品免费| 亚洲AV无码成人精品区天堂 | 91国内揄拍国内精品对白不卡| 91精品国产福利尤物| 国产午夜精品免费一区二区三区| 亚洲综合欧美精品一区二区| 欧美日韩国产中文精品字幕自在自线| 国产精品成人69XXX免费视频| 亚洲精品在线观看视频| 久久91精品国产91久久麻豆| 久久r热这里有精品视频| 亚洲精品国产成人专区| 久久这里只有精品久久| 香蕉久久夜色精品国产小说| 精品视频一区二区三区在线观看| 99精品免费视频| 久久久91精品国产一区二区三区| 久久精品这里热有精品| 午夜精品久视频在线观看| 777欧美午夜精品影院| 国产A∨免费精品视频| 国产VA免费精品高清在线| 国产精品毛片一区二区| 久久久WWW成人免费精品| 亚洲AV无码成人精品区狼人影院| 看99视频日韩精品|