成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

React性能優(yōu)化

n7then / 1178人閱讀

摘要:當(dāng)大家考慮在項(xiàng)目中使用的時(shí)候,第一個(gè)問題往往是他們的應(yīng)用的速度和響應(yīng)是否能和非版一樣,每當(dāng)狀態(tài)改變的時(shí)候就重新渲染組件的整個(gè)子樹,讓大家懷疑這會不會對性能造成負(fù)面影響。

當(dāng)大家考慮在項(xiàng)目中使用 React 的時(shí)候,第一個(gè)問題往往是他們的應(yīng)用的速度和響應(yīng)是否能和非 React 版一樣,每當(dāng)狀態(tài)改變的時(shí)候就重新渲染組件的整個(gè)子樹,讓大家懷疑這會不會對性能造成負(fù)面影響。React 用了一些黑科技來減少 UI 更新需要的花費(fèi)較大的 DOM 操作。

使用 production 版本

如果你在你的 React app 中進(jìn)行性能測試或在尋找性能問題,一定要確定你在使用 minified production build。開發(fā)者版本包括額外的警告信息,這對你在開發(fā)你的 app 的時(shí)候很有用,但是因?yàn)橐M(jìn)行額外的處理,所以它也會比較慢。

避免更新 DOM

React 使用虛擬 DOM,它是在瀏覽器中的 DOM 子樹的渲染描述,這個(gè)平行的描述讓 React 避免創(chuàng)建和操作 DOM 節(jié)點(diǎn),這些遠(yuǎn)比操作一個(gè) JavaScript 對象慢。當(dāng)一個(gè)組件的 props 或 state 改變,React 會構(gòu)造一個(gè)新的虛擬 DOM 和舊的進(jìn)行對比來決定真實(shí) DOM 更新的必要性,只有在它們不相等的時(shí)候,React 才會使用盡量少的改動更新 DOM。

在此之上,React 提供了生命周期函數(shù) shouldComponentUpdate,在重新渲染機(jī)制回路(虛擬 DOM 對比和 DOM 更新)之前會被觸發(fā),賦予開發(fā)者跳過這個(gè)過程的能力。這個(gè)函數(shù)默認(rèn)返回 true,讓 React 執(zhí)行更新。

shouldComponentUpdate: function(nextProps, nextState) {
  return true;
}

一定要記住,React 會非常頻繁的調(diào)用這個(gè)函數(shù),所以要確保它的執(zhí)行速度夠快。

假如你有個(gè)帶有多個(gè)對話的消息應(yīng)用,如果只有一個(gè)對話發(fā)生改變,如果我們在 ChatThread 組件執(zhí)行 shouldComponentUpdate,React 可以跳過其他對話的重新渲染步驟。

shouldComponentUpdate: function(nextProps, nextState) {
  // TODO: return whether or not current chat thread is
  // different to former one.
}

因此,總的說,React 通過讓用戶使用 shouldComponentUpdate 減短重新渲染回路,避免進(jìn)行昂貴的更新 DOM 子樹的操作,而且這些必要的更新,需要對比虛擬 DOM。

shouldComponentUpdate 實(shí)戰(zhàn)

這里有個(gè)組件的子樹,每一個(gè)都指明了 shouldComponentUpdate 返回值和虛擬 DOM 是否相等,最后,圓圈的顏色表示組件是否需要更新。

在上面的示例中,因?yàn)?C2 的 shouldComponentUpdate 返回 false,React 就不需要生成新的虛擬 DOM,也就不需要更新 DOM,注意 React 甚至不需要調(diào)用 C4 和 C5 的 shouldComponentUpdate

C1 和 C3 的 shouldComponentUpdate 返回 true,所以 React 需要向下到葉子節(jié)點(diǎn)檢查它們,C6 返回 true,因?yàn)樘摂M DOM 不相等,需要更新 DOM。最后感興趣的是 C8,對于這個(gè)節(jié)點(diǎn),React 需要計(jì)算虛擬 DOM,但是因?yàn)樗团f的相等,所以不需要更新 DOM。

注意 React 只需要對 C6 進(jìn)行 DOM 轉(zhuǎn)換,這是必須的。對于 C8,通過虛擬 DOM 的對比確定它是不需要的,C2 的子樹和 C7,它們甚至不需要計(jì)算虛擬 DOM,因?yàn)?shouldComponentUpdate。

那么,我們怎么實(shí)現(xiàn) shouldComponentUpdate 呢?比如說你有一個(gè)組件僅僅渲染一個(gè)字符串:

React.createClass({
  propTypes: {
    value: React.PropTypes.string.isRequired
  },

  render: function() {
    return 
{this.props.value}
; } });

我們可以簡單的實(shí)現(xiàn) shouldComponentUpdate 如下:

shouldComponentUpdate: function(nextProps, nextState) {
  return this.props.value !== nextProps.value;
}

非常好!處理這樣簡單結(jié)構(gòu)的 props/state 很簡單,我門甚至可以歸納出一個(gè)基于淺對比的實(shí)現(xiàn),然后把它 Mixin 到組件中。實(shí)際上 React 已經(jīng)提供了這樣的實(shí)現(xiàn): PureRenderMixin

但是如果你的組件的 props 或者 state 是可變的數(shù)據(jù)結(jié)構(gòu)呢?比如說,組件接收的 prop 不是一個(gè)像 "bar" 這樣的字符串,而是一個(gè)包涵字符串的 JavaScript 對象,比如 { foo: "bar" }:

React.createClass({
  propTypes: {
    value: React.PropTypes.object.isRequired
  },

  render: function() {
    return 
{this.props.value.foo}
; } });

前面的 shouldComponentUpdate 實(shí)現(xiàn)就不會一直和我們期望的一樣工作:

// assume this.props.value is { foo: "bar" }
// assume nextProps.value is { foo: "bar" },
// but this reference is different to this.props.value
this.props.value !== nextProps.value; // true

這個(gè)問題是當(dāng) prop 沒有改變的時(shí)候 shouldComponentUpdate 也會返回 true。為了解決這個(gè)問題,我們有了這個(gè)替代實(shí)現(xiàn):

shouldComponentUpdate: function(nextProps, nextState) {
  return this.props.value.foo !== nextProps.value.foo;
}

基本上,我們結(jié)束了使用深度對比來確保改變的正確跟蹤,這個(gè)方法在性能上的花費(fèi)是很大的,因?yàn)槲覀冃枰獮槊總€(gè) model 寫不同的深度對比代碼。就算這樣,如果我們沒有處理好對象引用,它甚至不能工作,比如說這個(gè)父組件:

React.createClass({
  getInitialState: function() {
    return { value: { foo: "bar" } };
  },

  onClick: function() {
    var value = this.state.value;
    value.foo += "bar"; // ANTI-PATTERN!
    this.setState({ value: value });
  },

  render: function() {
    return (
      
    );
  }
});

內(nèi)部組件第一次渲染的時(shí)候,它會獲取 { foo: "bar" } 作為 value 的值。如果用戶點(diǎn)擊了 a 標(biāo)簽,父組件的 state 會更新成 { value: { foo: "barbar" } },觸發(fā)內(nèi)部組件的重新渲染過程,內(nèi)部組件會收到 { foo: "barbar" } 作為 value 的新的值。

這里的問題是因?yàn)楦附M件和內(nèi)部組件共享同一個(gè)對象的引用,當(dāng)對象在 onClick 函數(shù)的第二行發(fā)生改變的時(shí)候,內(nèi)部組件的屬性也發(fā)生了改變,所以當(dāng)重新渲染過程開始,shouldComponentUpdate 被調(diào)用的時(shí)候,this.props.value.foonextProps.value.foo 是相等的,因?yàn)閷?shí)際上 this.props.valuenextProps.value 是同一個(gè)對象的引用。

因此,我們會丟失 prop 的改變,縮短重新渲染過程,UI 也不會從 "bar" 更新到 "barbar"

Immutable-js 來救贖

Immutable-js 是 Lee Byron 寫的 JavaScript 集合類型的庫,最近被 Facebook 開源,它通過結(jié)構(gòu)共享提供不可變持久化集合類型。一起看下這些特性的含義:

Immutable: 一旦創(chuàng)建,集合就不能再改變。

Persistent: 新的集合類型可以通過之前的集合創(chuàng)建,比如 set 產(chǎn)生改變的集合。創(chuàng)建新的集合之后源集合仍然有效。

Structural Sharing: 新的集合會使用盡量多的源集合的結(jié)構(gòu),減少復(fù)制來節(jié)省空間和性能友好。如果新的集合和源集合相等,一般會返回源結(jié)構(gòu)。

不可變讓跟蹤改變非常簡單;每次改變都是產(chǎn)生新的對象,所以我們僅需要對象的引用是否改變,比如這段簡單的 JavaScript 代碼:

var x = { foo: "bar" };
var y = x;
y.foo = "baz";
x === y; // true

盡管 y 被改變,因?yàn)樗?x 引用的是同一個(gè)對象,這個(gè)對比返回 true。然而,這個(gè)代碼可以使用 immutable-js 改寫如下:

var SomeRecord = Immutable.Record({ foo: null });
var x = new SomeRecord({ foo: "bar"  });
var y = x.set("foo", "baz");
x === y; // false

這個(gè)例子中,因?yàn)楦淖?x 的時(shí)候返回了新的引用,我們就可以安全的認(rèn)為 x 已經(jīng)改變。

臟檢測可以作為另外的可行的方式追蹤改變,給 setters 一個(gè)標(biāo)示。這個(gè)方法的問題是,它強(qiáng)制你使用 setters,而且要寫很多額外的代碼,影響你的類?;蛘吣憧梢栽诟淖冎吧羁截悓ο?,然后進(jìn)行深對比來確定是不是發(fā)生了改變。這個(gè)方法的問題是,深拷貝和深對比都是很花性能的操作。

因此,不可變數(shù)據(jù)結(jié)構(gòu)給你提供了一個(gè)高效、簡潔的方式來跟蹤對象的改變,而跟蹤改變是實(shí)現(xiàn) shouldComponentUpdate 的關(guān)鍵。所以,如果我們使用 immutable-js 提供的抽象創(chuàng)建 props 和 state 模型,我們就可以使用 PureRenderMixin,而且能夠獲得很好的性能增強(qiáng)。

Immutable-js 和 Flux

如果你在使用 Flux,你應(yīng)該開始使用 immutable-js 寫你的 stores,看一下 full API。

讓我們看一個(gè)可行的方式,使用不可變數(shù)據(jù)結(jié)構(gòu)來給消息示例創(chuàng)建數(shù)據(jù)結(jié)構(gòu)。首先我們要給每個(gè)要建模的實(shí)體定義一個(gè) Record。Records 僅僅是一個(gè)不可變?nèi)萜?,里面保存一系列具體數(shù)據(jù):

var User = Immutable.Record({
  id: undefined,
  name: undefined,
  email: undefined
});

var Message = Immutable.Record({
  timestamp: new Date(),
  sender: undefined,
  text: ""
});

Record 方法接收一個(gè)對象,來定義字段和對應(yīng)的默認(rèn)數(shù)據(jù)。

消息的 store 可以使用兩個(gè) list 來跟蹤 users 和 messages:

this.users = Immutable.List();
this.messages = Immutable.List();

實(shí)現(xiàn)函數(shù)處理每個(gè) payload 類型應(yīng)該是比較簡單的,比如,當(dāng) store 看到一個(gè)代表新消息的 payload 時(shí),我們就創(chuàng)建一個(gè)新的 record,并放入消息列表:

this.messages = this.messages.push(new Message({
  timestamp: payload.timestamp,
  sender: payload.sender,
  text: payload.text
});

注意:因?yàn)閿?shù)據(jù)結(jié)構(gòu)不可變,我們需要把 push 方法的結(jié)果賦給 this.messages。

在 React 里,如果我們也使用 immutable-js 數(shù)據(jù)結(jié)構(gòu)來保存組件的 state,我門可以把 PureRenderMixin 混入到我門所有的組件來縮短重新渲染回路。

這篇文章是翻譯React官方文檔

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/87824.html

相關(guān)文章

  • 4、React組件之性能優(yōu)化

    摘要:組件的性能優(yōu)化高德納我們應(yīng)該忘記忽略很小的性能優(yōu)化,可以說的情況下,過早的優(yōu)化是萬惡之源,而我們應(yīng)該關(guān)心對性能影響最關(guān)鍵的另外的代碼。對多個(gè)組件的性能優(yōu)化當(dāng)一個(gè)組件被裝載更新和卸載時(shí),組件的一序列生命周期函數(shù)會被調(diào)用。 React組件的性能優(yōu)化 高德納: 我們應(yīng)該忘記忽略很小的性能優(yōu)化,可以說97%的情況下,過早的優(yōu)化是萬惡之源,而我們應(yīng)該關(guān)心對性能影響最關(guān)鍵的另外3%的代碼。...

    陳偉 評論0 收藏0
  • 【騰訊Bugly干貨分享】React 移動 web 極致優(yōu)化

    摘要:數(shù)據(jù)管理及性能優(yōu)化統(tǒng)一管理數(shù)據(jù)這一部份算是重頭戲吧。重復(fù)渲染導(dǎo)致卡頓這套的東西在家校群頁面上用得很歡樂,以至于不用怎么寫都沒遇到過什么性能問題。但放到移動端上,我們在列表頁重構(gòu)的時(shí)候就馬上遇到卡頓的問題了。列表頁目前的處理辦法是將值換成。 本文來自于騰訊bugly開發(fā)者社區(qū),非經(jīng)作者同意,請勿轉(zhuǎn)載,原文地址:http://dev.qq.com/topic/57908... 最近一個(gè)季度...

    suosuopuo 評論0 收藏0
  • 程序員練級攻略(2018):前端性能優(yōu)化和框架

    摘要:,谷歌給的一份性能指南和最佳實(shí)踐。目前而言,前端社區(qū)有三大框架和。隨后重點(diǎn)講述了和兩大前端框架,給出了大量的文章教程和相關(guān)資源列表。我認(rèn)為,使用函數(shù)式編程方式,更加符合后端程序員的思路,而是更符合前端工程師習(xí)慣的框架。 showImg(https://segmentfault.com/img/bVbjQAM?w=1142&h=640); 這個(gè)是我訂閱 陳皓老師在極客上的專欄《左耳聽風(fēng)》...

    VEIGHTZ 評論0 收藏0
  • 程序員練級攻略(2018):前端性能優(yōu)化和框架

    摘要:,谷歌給的一份性能指南和最佳實(shí)踐。目前而言,前端社區(qū)有三大框架和。隨后重點(diǎn)講述了和兩大前端框架,給出了大量的文章教程和相關(guān)資源列表。我認(rèn)為,使用函數(shù)式編程方式,更加符合后端程序員的思路,而是更符合前端工程師習(xí)慣的框架。 showImg(https://segmentfault.com/img/bVbjQAM?w=1142&h=640); 這個(gè)是我訂閱 陳皓老師在極客上的專欄《左耳聽風(fēng)》...

    CoffeX 評論0 收藏0
  • 個(gè)人常用JavaScript及React常用優(yōu)化總結(jié)

    摘要:插件性能優(yōu)化及個(gè)人常用優(yōu)化方法經(jīng)常會觸發(fā)視覺變化。作用域鏈指的是當(dāng)前作用于下可用變量的集合,它在各種主流瀏覽器中至少包含兩個(gè)部分局部變量的集合和全局變量的集合。在考慮優(yōu)化時(shí),數(shù)值和變量的性能差不多,并且速度顯著優(yōu)于對象屬性和數(shù)組元素。 JavaScript 插件性能優(yōu)化及個(gè)人react常用優(yōu)化方法 JavaScript 經(jīng)常會觸發(fā)視覺變化。有時(shí)是直接通過樣式操作,有時(shí)是會產(chǎn)生視覺變化...

    yuanxin 評論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)化的文章都會談及內(nèi)聯(lián)函數(shù),其也是常見的被詬病為拖慢性能表現(xiàn)的元兇之一不過本文卻是打破砂鍋問到底,論證了內(nèi)聯(lián)函數(shù)并不一定就會拖慢性能,過度的性能優(yōu)化反而會有損于應(yīng)用性能。 showImg(https://segmentfault.com/img/remote/1460000011481413?w=1240&h=825); 前端每周...

    CoderStudy 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<