亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

React學(xué)習(xí)之前端開發(fā)性能優(yōu)化

channg / 3289人閱讀

摘要:單個(gè)組件性能優(yōu)化里面盡量減少新建變量和函數(shù)的使用,盡量減少傳遞參數(shù)的數(shù)量在中綁定函數(shù),無非就是下面三種第一種是在構(gòu)造函數(shù)中綁定,第二種是在函數(shù)里面綁定,第三種就是使用箭頭函數(shù),上述方法都能實(shí)現(xiàn)的綁定。

1. 單個(gè)react組件性能優(yōu)化 1.1 render里面盡量減少新建變量和bind函數(shù)的使用,盡量減少傳遞參數(shù)的數(shù)量

render中綁定函數(shù),無非就是下面三種:

render() {
  return (
    
1 2 this.handleClick()}>3
) }

第一種是在構(gòu)造函數(shù)中綁定this,第二種是在render()函數(shù)里面綁定this,第三種就是使用箭頭函數(shù),上述方法都能實(shí)現(xiàn)this的綁定。

但是哪一種方法的性能最好,是我們要考慮的問題。毫無疑問第一種的性能最好。

第一種方法,構(gòu)造函數(shù)每渲染一次便會(huì)執(zhí)行一遍;

第二種方法,在每次render()的時(shí)候都會(huì)重新執(zhí)行一遍函數(shù);

第三種方法,每一次render()的時(shí)候,都會(huì)生成一個(gè)新的箭頭函數(shù),即使兩個(gè)箭頭函數(shù)的內(nèi)容是一樣的。

react判斷是否需要進(jìn)行render淺層比較,簡單來說就是通過===來判斷的,如果state或者prop的類型是字符串或者數(shù)字,只要值相同,那么淺層比較就會(huì)認(rèn)為其相同;

但是如果前者的類型是復(fù)雜的對(duì)象的時(shí)候,我們知道對(duì)象是引用類型,淺層比較只會(huì)認(rèn)為這兩個(gè)prop是不是同一個(gè)引用,如果不是,哪怕這兩個(gè)對(duì)象中的內(nèi)容完全一樣,也會(huì)被認(rèn)為是兩個(gè)不同的prop。

舉個(gè)例子:

當(dāng)我們給組件App名為styleprop賦值;


使用這種方法,每一次渲染都會(huì)被認(rèn)為是一個(gè)style這個(gè)prop發(fā)生了變化,因?yàn)槊恳淮味紩?huì)產(chǎn)生一個(gè)對(duì)象給style。

如果想要讓react渲染的時(shí)候認(rèn)為前后對(duì)象類型prop相同,則必須要保證prop指向同一個(gè)javascript對(duì)象,改進(jìn)如下:

const appStyle = { color: "red" }; //這個(gè)初始化只執(zhí)行一次,不要放在render中,可以放在構(gòu)造函數(shù)中
1.2 定制shouldComponentUpdate函數(shù)

生命周期函數(shù)shouldComponentUpdate是決定react組件什么時(shí)候能夠重新渲染的函數(shù),但是這個(gè)函數(shù)默認(rèn)的實(shí)現(xiàn)方式就是簡單的返回一個(gè)true。也就是說,默認(rèn)每次更新的時(shí)候都要調(diào)用所用的生命周期函數(shù),包括render函數(shù),重新渲染。

看看下面這個(gè)例子:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count = 2,
      name = "apple",
    }
    this.handleClick = this.handleClick.bind(this);
    this.handleName = this.handleName.bind(this);
  }
  this.handleClick() {
  // ...
  }
  this.handleName() {
  // ...
  }
  render() {
    return (
      
數(shù)量,{this.state.count}
); } } class Child extends React.Component { render() { console.log("render了一次"); return (

我想吃,{this.props.title}

); } }

我們寫了兩個(gè)組件,AppChild組件,并寫兩個(gè)方法,一個(gè)改變App中的count的值,一個(gè)是改變name,我們?cè)?b>Child的render中打印了每次是否執(zhí)行。

不出意外,雖然Child組件里的title值沒有改變,但是還是render了。

為了進(jìn)一步優(yōu)化這個(gè)問題,我們這樣改Child組件:

class Child extends React.Component {
  shouldComponentUpdate(nextProps,nextState) {
    if(nextProps.title == this.props.title) {
      return false;
    }
    return true;
  }

  render() {
    console.log("render了一次");
    return (
      

我想吃,{this.props.title}

); } }

只有當(dāng)Childtitle值發(fā)生改變的時(shí)候,組件才會(huì)去render。

在最新的react中,react給我們提供了React.PureComponent,官方也在早期提供了名為react-addons-pure-render-mixin插件來重新實(shí)現(xiàn)shouldComponentUpdate生命周期方法。

class Child extends React.PureComponent {
  // shouldComponentUpdate(nextProps,nextState) {
  //   if(nextProps.title == this.props.title) {
  //     return false;
  //   }
  //   return true;
  // }

  render() {
    console.log("render了一次");
    return (
      

我想吃,{this.props.title}

); } }

通過上述的方法的效果也是和我們先前定制shouldComponentUpdate的效果是一致的。

但是我們要注意的是,這里的PureRender是淺比較的,因?yàn)樯畋容^的場(chǎng)景是相當(dāng)昂貴的。所以我們要注意我們?cè)?b>1.1中說到的一些注意點(diǎn):不要直接為props設(shè)置對(duì)象或者數(shù)組不要將方法直接綁定在元素上,因?yàn)槠鋵?shí)函數(shù)也是對(duì)象。

1.3 Immutable.js

javascript中的對(duì)象一般都是可變的,因?yàn)槭褂昧艘觅x值,新的對(duì)象簡單的引用了原始對(duì)象,改變新對(duì)象將影響到原始對(duì)象。

舉個(gè)例子:

student = { age : 1 };
school = student;
school.age = 2;

當(dāng)我們給school.age賦值后,會(huì)發(fā)現(xiàn)student.a也變成了2,雖然我們可以通過深拷貝與淺拷貝解決這個(gè)問題,但是這樣做非常的昂貴,對(duì)cpu和內(nèi)存會(huì)造成浪費(fèi)。

這里就需要用到Immutable,通過Immutable創(chuàng)建的Immutable Data一旦被創(chuàng)建,就不能再更改。對(duì)Immutable對(duì)象進(jìn)行修改、添加或刪除操作,都會(huì)返回一個(gè)新的Immutable對(duì)象。

下面是三個(gè)比較重要且用到的數(shù)據(jù)結(jié)構(gòu)

Map:鍵值對(duì)集合,對(duì)應(yīng)Object,ES6中也有專門的Map對(duì)象

List:有序可重復(fù)列表,對(duì)應(yīng)于Array

ArraySet:有序且不可重復(fù)的列表

我們可以看一個(gè)例子:

使用Map生成一個(gè)immutable對(duì)象:

import { Map, is } from "immutable";

let a = Map({
  "name": "apple",
  "list": Map({name: "orange"})
})

let b = a.set("name","banana");

console.log(a.get("course") === b.get("course")); // 返回true
console.log(a === b); // 返回false

Immutable.is 比較的是兩個(gè)對(duì)象的 hashCodevalueOf(對(duì)于JavaScript對(duì)象)。由于immutable內(nèi)部使用了Trie數(shù)據(jù)結(jié)構(gòu)來存儲(chǔ),只要兩個(gè)對(duì)象的 hashCode 相等,值就是一樣的。這樣的算法避免了深度遍歷比較,性能非常好。

Immutable優(yōu)點(diǎn)

減少內(nèi)存的使用

并發(fā)安全

降低項(xiàng)目的復(fù)雜度

便于比較復(fù)雜數(shù)據(jù),定制shouldComponentUpdate方便

時(shí)間旅行功能

函數(shù)式編程

Immutable缺點(diǎn)

學(xué)習(xí)成本

庫的大?。ńㄗh使用seamless-immutable

對(duì)現(xiàn)有項(xiàng)目入侵嚴(yán)重

容易與原生的對(duì)象進(jìn)行混淆

2. 多個(gè)react組件性能優(yōu)化

react組件在裝載過程中,react通過在render方法在內(nèi)存中產(chǎn)生一個(gè)樹形結(jié)構(gòu),樹上的節(jié)點(diǎn)代表一個(gè)react組件或者原生的Dom元素,這個(gè)樹形結(jié)構(gòu)就是我們所謂的Vitural Domreact根據(jù)這個(gè)來渲染產(chǎn)生瀏覽器的Dom樹。

react在更新階段對(duì)比原有的Vitural Dom和新生成的Vitural Dom,找出不同之處,在根據(jù)不同來渲染Dom樹。

react為了追求高性能,采用了時(shí)間復(fù)雜度為O(N)來比較兩個(gè)屬性結(jié)構(gòu)的區(qū)別,因?yàn)橐_切比較兩個(gè)樹形結(jié)構(gòu),需要通過O(N^3),這會(huì)降低性能。

節(jié)點(diǎn)類型不同

// A組件
// B組件

我們想把A組件更新成B組件,react在做比較的時(shí)候,發(fā)現(xiàn)最外面的根結(jié)點(diǎn)完全不一樣,直接銷毀之前的

節(jié)點(diǎn),包括里面的子節(jié)點(diǎn)也一并銷毀,這是一個(gè)巨大的浪費(fèi),但是為了避免O(N^3)的時(shí)間復(fù)雜度,只能采用這種方式。

所以在開發(fā)過程中,我們應(yīng)該盡量避免上面的情況,不要將包裹節(jié)點(diǎn)的類型隨意改變。

兩個(gè)節(jié)點(diǎn)類型一樣

這里包括兩種情況,一種是節(jié)點(diǎn)是Dom類型,還有一種react組件。

對(duì)于dom類型,我們舉個(gè)例子:

// A組件
Hello World!!!
// B組件
Good Bye!!!

上述A和B組件的區(qū)別是文字、className、style中的color發(fā)生改變,因?yàn)?b>Dom元素沒變,React只會(huì)修改他變化的部分。

針對(duì)react組件類型,渲染無非就是再執(zhí)行一遍組件實(shí)例的更新過程,最主要的就是定制shouldComponentUpdate。

多個(gè)子組件情況

例子一:

// A
// B

從A變到B,如果shouldComponentUpdate處理得當(dāng),我們只需要更新裝載third的那一次就行。

我們來看看下一個(gè)例子:

// A
// B

這里因?yàn)?b>react是采用O(n)的時(shí)間復(fù)雜度,所以會(huì)依次將textFirst的改為Zero,textSecond改為First,在最后再加上一個(gè)組件,textSecond。現(xiàn)存的兩個(gè)的text的屬性都被改變了,所以會(huì)依次渲染。

如果我們這里有100個(gè)實(shí)例,那么就會(huì)發(fā)生100次更新。

這里我們就要用到Key

簡單來說,其實(shí)這一個(gè)Key就是react組件的身份證號(hào)。

我們將上一個(gè)例子改成如下,就可以避免上面的問題了,react就能夠知道其實(shí)B里面的第二個(gè)和第三個(gè)組件其實(shí)就是A中的第一個(gè)和第二個(gè)實(shí)例。

// A
// B

不過現(xiàn)在,react也會(huì)提醒我們不要忘記使用key,如果沒有加,瀏覽器中會(huì)報(bào)錯(cuò)。

關(guān)于key的使用我們要注意的是,這個(gè)key值要穩(wěn)定不變的,就如同身份證號(hào)對(duì)于我們是穩(wěn)定不變的一樣。

一個(gè)常見的錯(cuò)誤就是,拿數(shù)組的的下標(biāo)值去當(dāng)做key,這個(gè)是很危險(xiǎn)的,代碼如下,我們一定要避免

    { todos.map((item, index) => { }) }

未完待續(xù)...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/105573.html

相關(guān)文章

  • 前端每周清單第 48 期:Slack Webpack 構(gòu)建優(yōu)化,CSS 命名規(guī)范與用戶追蹤,Vue.

    摘要:發(fā)布是由團(tuán)隊(duì)開源的,操作接口庫,已成為事實(shí)上的瀏覽器操作標(biāo)準(zhǔn)。本周正式發(fā)布,為我們帶來了,,支持自定義頭部與腳部,支持增強(qiáng),兼容原生協(xié)議等特性變化。新特性介紹日前發(fā)布了大版本更新,引入了一系列的新特性與提升,本文即是對(duì)這些變化進(jìn)行深入解讀。 showImg(https://segmentfault.com/img/remote/1460000012940044); 前端每周清單專注前端...

    sean 評(píng)論0 收藏0
  • 前端每周清單第 34 期:Vue 現(xiàn)狀盤點(diǎn)與 3.0 展望,React 代碼遷移與優(yōu)化,圖片優(yōu)化詳論

    摘要:工程實(shí)踐立足實(shí)踐,提示實(shí)際水平內(nèi)聯(lián)函數(shù)與性能很多關(guān)于性能優(yōu)化的文章都會(huì)談及內(nèi)聯(lián)函數(shù),其也是常見的被詬病為拖慢性能表現(xiàn)的元兇之一不過本文卻是打破砂鍋問到底,論證了內(nèi)聯(lián)函數(shù)并不一定就會(huì)拖慢性能,過度的性能優(yōu)化反而會(huì)有損于應(yīng)用性能。 showImg(https://segmentfault.com/img/remote/1460000011481413?w=1240&h=825); 前端每周...

    CoderStudy 評(píng)論0 收藏0
  • 王下邀月熊_Chevalier的前端每周清單系列文章索引

    摘要:感謝王下邀月熊分享的前端每周清單,為方便大家閱讀,特整理一份索引。王下邀月熊大大也于年月日整理了自己的前端每周清單系列,并以年月為單位進(jìn)行分類,具體內(nèi)容看這里前端每周清單年度總結(jié)與盤點(diǎn)。 感謝 王下邀月熊_Chevalier 分享的前端每周清單,為方便大家閱讀,特整理一份索引。 王下邀月熊大大也于 2018 年 3 月 31 日整理了自己的前端每周清單系列,并以年/月為單位進(jìn)行分類,具...

    2501207950 評(píng)論0 收藏0
  • 前端每周清單第 41 期 : Node 與 Rust、OpenCV 的火花,網(wǎng)絡(luò)安全二三事

    摘要:的網(wǎng)站仍然使用有漏洞庫上周發(fā)布了開源社區(qū)安全現(xiàn)狀報(bào)告,發(fā)現(xiàn)隨著開源社區(qū)的日漸活躍,開源代碼中包含的安全漏洞以及影響的范圍也在不斷擴(kuò)大。與應(yīng)用安全是流行的服務(wù)端框架,本文即是介紹如何使用以及其他的框架來增強(qiáng)應(yīng)用的安全性。 showImg(https://segmentfault.com/img/remote/1460000012181337?w=1240&h=826); 前端每周清單專注...

    syoya 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<