搜尋
首頁web前端js教程React框架有哪些演算法? react框架的演算法詳解

本篇文章主要的講述了關於react框架的原理詳解,下面還有很多關於react的深入了解,現在就讓我們一起來看看這篇文章吧

#React 搞了2年多了,對這門框架可謂又愛又恨,它的優勢大家都熟知,但是缺點也漸漸暴露,一個大型項目裡,配合ReduxReactRouter等三方框架後,結合複雜的業務程式碼量會變得非常大(前端程式碼常常是以前的1.5倍)。如果前期底層設計得不好,時常面臨開發效率低的問題。下面歸納了一些React框架的核心概念,希望對大家有幫助:

React diff 演算法

React的diff演算法是Virtual DOM之所以任性的最大依仗,大家知道頁面的性能一般是由渲染速度和渲染次數決定,如何最大程度地利用diff演算法進行開發?我們先看看它的原理。

傳統diff 演算法

計算一棵樹形結構轉換成另一棵樹形結構的最少操作,傳統diff 演算法透過循環遞歸對節點進行依次對比,效率低下,演算法複雜度達到O(n^3),其中n 是樹中節點的總數。也就是說如果要展示1000個節點,就要依序執行上十億次的比較。這個效能消耗對對於前端專案來說是不可接受的。

核心演算法

如上所見,傳統 diff 演算法的複雜度為 O(n^3),顯然這是無法滿足效能要求的。而React透過制定大膽的策略,將 O(n^3) 複雜度的問題轉換成 O(n) 複雜度的問題。他是怎麼做到的?

tree diff

Web UI 中 DOM 節點跨層級的移動操作特別少,可以忽略不計。 React 對樹的演算法進行了簡潔明了的最佳化,即對樹進行分層比較,兩棵樹只會對同一層次的節點進行比較。如下圖所示:

React框架有哪些演算法? react框架的演算法詳解

React 透過updateDepth 對Virtual DOM 樹進行層級控制,只會對相同顏色方塊內的DOM 節點進行比較,即同一個父節點下的所有子節點。當發現節點已經不存在,則該節點及其子節點會被完全刪除掉,不會用於進一步的比較。這樣只需要對樹進行一次遍歷,便能完成整個 DOM 樹的比較。

// tree diff算法实现updateChildren: function(nextNestedChildrenElements, transaction, context) {
  updateDepth++;  var errorThrown = true;  try {    this._updateChildren(nextNestedChildrenElements, transaction, context);
    errorThrown = false;
  } finally {
    updateDepth--;    if (!updateDepth) {      if (errorThrown) {
        clearQueue();
      } else {
        processQueue();
      }
    }
  }
}

為什麼要減少DOM節點的跨層級運算?

如下圖,A 節點(包括其子節點)整個被移動到D 節點下,由於React 只會簡單的考慮同層級節點的位置變換,而對於不同層級的節點,只有建立和刪除操作。當根節點發現子節點中 A 消失了,就會直接銷毀 A;當 D 發現多了一個子節點 A,則會建立新的 A(包括子節點)作為其子節點。此時,React diff 的執行情況:create A -> create B -> create C -> delete A。

React框架有哪些演算法? react框架的演算法詳解

由此可發現,當節點跨層級移動時,並不會出現想像中的移動操作,而是以A 為根節點的樹被整個重新創建,這是一種影響React 效能的操作。

component diff

擁有相同類別的兩個元件將會產生相似的樹狀結構,擁有不同類別的兩個元件將會產生不同的樹形結構。

  • 如果是相同類型的元件,請依照原始策略繼續比較 virtual DOM tree

  • 如果不是,則將該元件判斷為 dirty component,從而替換整個元件下的所有子節點。

  • 對於同一類型的元件,有可能其Virtual DOM 沒有任何變化,如果能夠確切的知道這點那可以節省大量的diff 運算時間,因此React 允許使用者透過shouldComponentUpdate() 來判斷該元件是否需要進行diff。

React框架有哪些演算法? react框架的演算法詳解

如上圖,當component D 改變為component G 時,即使這兩個component 結構相似,一旦React 判斷D 和G 是不同類型的元件,就不會比較二者的結構,而是直接刪除component D,重新建立component G 以及其子節點。雖然當兩個component 是不同類型但結構相似時,React diff 會影響效能,但正如React 官方部落格所言:不同類型的component 是很少存在相似DOM tree 的機會,因此這種極端因素很難在實現開發過程中造成重大影響的。

element diff

對於同一層級的一組子節點,它們可以透過唯一 id 來區分。 React 提出最佳化策略:讓開發者對同一層級的同組子節點,增加唯一 key 進行區分,雖然只是小小的改動,但效能上卻發生了翻天覆地的變化!

新舊集合所包含的節點,如下圖所示,新舊集合進行diff 差異化對比,透過key 發現新舊集合中的節點都是相同的節點,因此無需進行節點刪除和創建,只需要將舊集合中節點的位置進行移動,更新為新集合中節點的位置,此時React 給出的diff 結果為:B、D 不做任何操作,A、C 進行移動操作,即可。

React框架有哪些演算法? react框架的演算法詳解

開發建議

(1)[基於tree diff] 開發元件時,保持穩定的DOM結構有助於維持整體的性能。換而言之,盡可能少地動態操作DOM結構,尤其是移動操作。當節點數過大或頁面更新次數過多時,頁面卡頓的現像比較明顯。可以透過 CSS 隱藏或顯示節點,而不是真的移除或新增 DOM 節點。

(2)[基於component diff] 開發元件時,請注意使用 shouldComponentUpdate() 來減少元件不必要的更新。除此之外,對於類似的結構應該盡量封裝成元件,既減少程式碼量,又能減少component diff的效能消耗。

(3)[基於element diff] 對於列表結構,盡量減少類似將最後一個節點移動到列表首部的操作,當節點數量過大或更新操作過於頻繁時,在一定程度上會影響React 的渲染效能。

React Lifecycle

React的生命週期具體可分為四種情況:

React框架有哪些演算法? react框架的演算法詳解

  • 當首次裝載元件時,依序執行getDefaultPropsgetInitialStatecomponentWillMountrendercomponentDidMount

  • ##當卸載元件時,執行componentWillUnmount

  • 當重新裝載元件時,此時會依序執行getInitialStatecomponentWillMountrendercomponentDidMount,但不執行getDefaultProps;

  • #當再次渲染元件時,元件接受到更新狀態,此時依序執行componentWillReceivePropsshouldComponentUpdatecomponentWillUpdaterendercomponentDidUpdate

React元件的3種狀態

狀態一:MOUNTING

mountComponent 負責管理生命週期中的 getInitialStatecomponentWillMountrendercomponentDidMount

React框架有哪些演算法? react框架的演算法詳解

狀態二:RECEIVE_PROPS

updateComponent 負責管理生命週期中的componentWillReceivePropsshouldComponentUpdate componentWillUpdaterendercomponentDidUpdate

React框架有哪些演算法? react框架的演算法詳解

狀態三:UNMOUNTING

unmountComponent 負責管理生命週期中的 componentWillUnmount。 (想看更多就到PHP中文網React參考手冊欄位學習)

先將狀態設定為UNMOUNTING,若有componentWillUnmount,則執行;如果此時在componentWillUnmount 中呼叫setState,是不會觸發reRender。更新狀態為 NULL,完成元件卸載作業。實作程式碼如下:

// 卸载组件unmountComponent: function() {
  // 设置状态为 UNMOUNTING
  this._compositeLifeCycleState = CompositeLifeCycle.UNMOUNTING;  // 如果存在 componentWillUnmount,则触发
  if (this.componentWillUnmount) {    this.componentWillUnmount();
  }  // 更新状态为 null
  this._compositeLifeCycleState = null;  this._renderedComponent.unmountComponent();  this._renderedComponent = null;

  ReactComponent.Mixin.unmountComponent.call(this);
}

React生命周期总结

React框架有哪些演算法? react框架的演算法詳解

生命周期 调用次数 能否使用setState()
getDefaultProps 1
getInitialState 1
componentWillMount 1
render >=1
componentDidMount 1
componentWillReceiveProps >=0
shouldComponentUpdate >=0
componentWillUpdate >=0
componentDidUpdate >=0
componentWillUnmount 1
componentDidUnmount 1

setState实现机制

setStateReact框架的核心方法之一,下面介绍一下它的原理:

React框架有哪些演算法? react框架的演算法詳解

// 更新 statesetState: function(partialState, callback) {
  // 合并 _pendingState
  this.replaceState(
    assign({}, this._pendingState || this.state, partialState),
    callback
  );
},

当调用 setState 时,会对 state 以及 _pendingState 更新队列进行合并操作,但其实真正更新 state 的幕后黑手是replaceState

// 更新 statereplaceState: function(completeState, callback) {
  validateLifeCycleOnReplaceState(this);  // 更新队列
  this._pendingState = completeState;  // 判断状态是否为 MOUNTING,如果不是,即可执行更新
  if (this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING) {
    ReactUpdates.enqueueUpdate(this, callback);
  }
},

replaceState 会先判断当前状态是否为 MOUNTING,如果不是即会调用 ReactUpdates.enqueueUpdate 执行更新。

当状态不为 MOUNTINGRECEIVING_PROPS 时,performUpdateIfNecessary 会获取 _pendingElement_pendingState_pendingForceUpdate,并调用 updateComponent 进行组件更新。

// 如果存在 _pendingElement、_pendingState、_pendingForceUpdate,则更新组件performUpdateIfNecessary: function(transaction) {
  var compositeLifeCycleState = this._compositeLifeCycleState;  // 当状态为 MOUNTING 或 RECEIVING_PROPS时,则不更新
  if (compositeLifeCycleState === CompositeLifeCycle.MOUNTING ||
      compositeLifeCycleState === CompositeLifeCycle.RECEIVING_PROPS) {    return;
  }  var prevElement = this._currentElement;  var nextElement = prevElement;  if (this._pendingElement != null) {
    nextElement = this._pendingElement;    this._pendingElement = null;
  }  // 调用 updateComponent
  this.updateComponent(
    transaction,
    prevElement,
    nextElement
  );
}

如果在 shouldComponentUpdatecomponentWillUpdate 中调用 setState,此时的状态已经从 RECEIVING_PROPS -> NULL,则 performUpdateIfNecessary 就会调用 updateComponent 进行组件更新,但 updateComponent 又会调用 shouldComponentUpdatecomponentWillUpdate,因此造成循环调用,使得浏览器内存占满后崩溃。

开发建议

不建议在 getDefaultPropsgetInitialStateshouldComponentUpdatecomponentWillUpdaterendercomponentWillUnmount 中调用 setState,特别注意:不能在 shouldComponentUpdatecomponentWillUpdate中调用 setState,会导致循环调用。

本篇文章到这就结束了(想看更多就到PHP中文网React使用手册栏目中学习),有问题的可以在下方留言提问。

以上是React框架有哪些演算法? react框架的演算法詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
解读CRISP-ML(Q):机器学习生命周期流程解读CRISP-ML(Q):机器学习生命周期流程Apr 08, 2023 pm 01:21 PM

译者 | 布加迪审校 | 孙淑娟目前,没有用于构建和管理机器学习(ML)应用程序的标准实践。机器学习项目组织得不好,缺乏可重复性,而且从长远来看容易彻底失败。因此,我们需要一套流程来帮助自己在整个机器学习生命周期中保持质量、可持续性、稳健性和成本管理。图1. 机器学习开发生命周期流程使用质量保证方法开发机器学习应用程序的跨行业标准流程(CRISP-ML(Q))是CRISP-DM的升级版,以确保机器学习产品的质量。CRISP-ML(Q)有六个单独的阶段:1. 业务和数据理解2. 数据准备3. 模型

thinkphp是不是国产框架thinkphp是不是国产框架Sep 26, 2022 pm 05:11 PM

thinkphp是国产框架。ThinkPHP是一个快速、兼容而且简单的轻量级国产PHP开发框架,是为了简化企业级应用开发和敏捷WEB应用开发而诞生的。ThinkPHP从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重易用性。

Python 强大的任务调度框架 Celery!Python 强大的任务调度框架 Celery!Apr 12, 2023 pm 09:55 PM

什么是 celery这次我们来介绍一下 Python 的一个第三方模块 celery,那么 celery 是什么呢? celery 是一个灵活且可靠的,处理大量消息的分布式系统,可以在多个节点之间处理某个任务; celery 是一个专注于实时处理的任务队列,支持任务调度; celery 是开源的,有很多的使用者; celery 完全基于 Python 语言编写;所以 celery 本质上就是一个任务调度框架,类似于 Apache 的 airflow,当然 airflow 也是基于 Python

6个推荐的Python框架,用于构建可解释的人工智能系统(XAI)6个推荐的Python框架,用于构建可解释的人工智能系统(XAI)Apr 26, 2023 am 10:49 AM

AI就像一个黑匣子,能自己做出决定,但是人们并不清楚其中缘由。建立一个AI模型,输入数据,然后再输出结果,但有一个问题就是我们不能解释AI为何会得出这样的结论。需要了解AI如何得出某个结论背后的原因,而不是仅仅接受一个在没有上下文或解释的情况下输出的结果。可解释性旨在帮助人们理解:如何学习的?学到了什么?针对一个特定输入为什么会做出如此决策?决策是否可靠?在本文中,我将介绍6个用于可解释性的Python框架。SHAPSHapleyAdditiveexplanation(SHapleyAdditi

如何在PHP中使用AOP框架如何在PHP中使用AOP框架May 19, 2023 pm 01:21 PM

AOP(面向切面编程)是一种编程思想,用于解耦业务逻辑和横切关注点(如日志、权限等)。在PHP中,使用AOP框架可以简化编码,提高代码可维护性和可扩展性。本文将介绍在PHP中使用AOP框架的基本原理和实现方法。一、AOP的概念和原理面向切面编程,指的是将程序的业务逻辑和横切关注点分离开来,通过AOP框架来实现统一管理。横切关注点指的是在程序中需要重复出现并且

Microsoft .NET Framework 4.5.2、4.6 和 4.6.1 将于 2022 年 4 月终止支持Microsoft .NET Framework 4.5.2、4.6 和 4.6.1 将于 2022 年 4 月终止支持Apr 17, 2023 pm 02:25 PM

已安装Microsoft.NET版本4.5.2、4.6或4.6.1的MicrosoftWindows用户如果希望Microsoft将来通过产品更新支持该框架,则必须安装较新版本的Microsoft框架。据微软称,这三个框架都将在2022年4月26日停止支持。支持日期结束后,产品将不会收到“安全修复或技术支持”。大多数家庭设备通过Windows更新保持最新。这些设备已经安装了较新版本的框架,例如.NETFramework4.8。未自动更新的设备可能

KB5013943 2022 年 5 月更新使 Windows 11 上的应用程序崩溃KB5013943 2022 年 5 月更新使 Windows 11 上的应用程序崩溃Apr 16, 2023 pm 10:52 PM

如果你在Windows11上安装了2022年5月累积更新,你可能已经注意到你一直使用的许多应用程序都不像以前那样工作了。强制性安全更新KB5013943正在使某些使用.NET框架的应用程序崩溃。在某些情况下,用户会收到错误代码:0xc0000135。可选更新中报告了类似的问题,但并不普遍。随着2022年5月的更新,该错误似乎已进入生产渠道,这次有更多用户受到影响。崩溃在使用.NETFramework的应用程序中很常见,Discord或MicrosoftTeams等

多模态再次统一!Meta发布自监督算法data2vec 2.0:训练效率最高提升16倍!多模态再次统一!Meta发布自监督算法data2vec 2.0:训练效率最高提升16倍!Apr 14, 2023 pm 04:10 PM

近几年人工智能领域的突破大多由自监督学习推动,比如BERT中提出的MLM(MaskedLanguageModel),通过将文本中的部分单词遮盖后重新预测,使得海量无标记文本数据也能用来训练模型,自此开启了大规模预训练模型的新时代。但自监督学习算法也有明显的局限性,通常只适用于单一模态(如图像、文本、语音等)的数据,并且需要大量的算力从海量数据中进行学习。相比之下,人类的学习效率要显著高于当前的AI模型,并且可以从不同类型的数据中进行学习。2022年1月,MetaAI发布了自监督学习框架data2

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器