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

資訊專欄INFORMATION COLUMN

React性能探索 --- 避免不必要渲染

missonce / 3208人閱讀

摘要:如何修復(fù)既然是不需要渲染,那就要阻止它的渲染。我個(gè)人覺得,在實(shí)際中,用跟兩個(gè)工具已經(jīng)可以很好幫我們判斷哪部分不需要重新渲染,幫助我們做出優(yōu)化。

背景

上一篇文章的結(jié)尾
http://imweb.io/topic/5985cc4...
我們說到,也許,不是所有的節(jié)點(diǎn)都需要重新渲染,對(duì)于那些不需要渲染的節(jié)點(diǎn),我們?nèi)绾握业剿鼈儾⒆鰞?yōu)化呢?

本篇文章來具體解答這個(gè)問題。

應(yīng)用分析

首先,先看這個(gè)應(yīng)用:頁面的兩部分分別渲染5000個(gè)節(jié)點(diǎn),從1-5000。當(dāng)點(diǎn)擊按鈕之后,第二部分的節(jié)點(diǎn)會(huì)更新,重新渲染從2-5001的數(shù)字,但是第一部分保持不變。

import React, { createElement, Component } from "react";
import {render} from "react-dom";
import Perf from "react-addons-perf";
import ListItem from "./ListItem"

function arrayGenerator(length) {
  return Array.apply(null, { length: length }).map(Number.call, Number)
}


class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      multiplier: 1
    }
  }

  resetMultiplier() {
    this.setState({ multiplier: 2 })
  }

  render() {
    return (
      
    { arrayGenerator(5000).map(i => { return }) } { arrayGenerator(5000).map(i => { return }) }
); } } render(,document.getElementById("main"));

gitbug 鏈接:
https://github.com/hhhuangqio...

感興趣的同學(xué)可以下載跑一跑代碼

分析更新時(shí)間

這里用react的Perf工具來測量重新渲染的時(shí)間。

使用方法:

npm install --save-dev react-addons-perf
import Perf from "react-addons-perf"

這里主要用到四個(gè)方法:

Perf.start():開始計(jì)時(shí)

Perf.stop():結(jié)束計(jì)時(shí)

Perf.printInclusive():打印組件總的渲染時(shí)間

Perf.printWasted():打印浪費(fèi)的時(shí)間

當(dāng)我們點(diǎn)擊按鈕,可以看到控制臺(tái)打印出下面的信息:

由控制臺(tái)的數(shù)據(jù)可以看出,App用了90.59ms渲染,其中渲染ListItem的時(shí)間為55ms,渲染了10000次,其中有5000次是浪費(fèi)的,因?yàn)檫@部分頁面的內(nèi)容完全沒有更新的改動(dòng)。

如何修復(fù)

既然是不需要渲染,那就要阻止它的渲染。React給我們提供了一個(gè)方法shouldComponentUpdate(),當(dāng)這個(gè)方法返回true的時(shí)候,需要重新渲染,false的時(shí)候不需要(默認(rèn)是true).

在這個(gè)栗子中,只要text的值不變,就不需要重新渲染。所以,可以這樣改寫ListItem 的shouldComponentUpdate

import React, { Component } from "react"

export default class ListItem extends Component {
  shouldComponentUpdate(nextProps, nextState) {
    return nextProps.text !== this.props.text  
  }

  render() {
    let { text } = this.props
    return 
  • {text}
  • } }

    在重新點(diǎn)擊一下按鈕,在控制臺(tái)可以發(fā)現(xiàn)

    App總的渲染時(shí)間降到了62.14ms,并且ListItem只重新渲染了5000個(gè)節(jié)點(diǎn),完全消除了浪費(fèi)的渲染。

    對(duì)于上面的寫法,React提供了一個(gè)新的組件PureComponent來做這件事,它會(huì)自動(dòng)淺對(duì)比props/state,當(dāng)兩者相同的時(shí)候不渲染節(jié)點(diǎn)。所以,listItem又可以改寫成

    import React, { PureComponent } from "react"
    
    export default class ListItem extends PureComponent {
      render() {
        let { text } = this.props
        return 
  • {text}
  • } }

    跑一跑代碼

    通過控制臺(tái)可以看到達(dá)到的效果是一樣的(有點(diǎn)誤差是正常的)。

    這里再安利一個(gè)可以發(fā)現(xiàn)應(yīng)用里是否存在不該重新渲染的節(jié)點(diǎn)工具:why-did-you-update

    使用方法
    1、npm i --save-dev why-did-you-update
    2、
    import React from "react"
    if (process.env.NODE_ENV !== "production") {
      const {whyDidYouUpdate} = require("why-did-you-update")
      whyDidYouUpdate(React)
    }

    然后點(diǎn)擊按鈕看控制臺(tái)


    可以看到Value did not change. Avoidable re-render!的警告,是不是很實(shí)用!

    注意的點(diǎn)

    PureComponent只會(huì)淺比較,所以不適合用于深層嵌套的對(duì)象。同時(shí),PureComponent不僅僅會(huì)跳過自己的重新渲染,還會(huì)跳過它所有子節(jié)點(diǎn)的,所以要注意,用它的時(shí)候是最好沒有子節(jié)點(diǎn)并且不依賴于global state的展示型組件。

    與Staleless的關(guān)系

    不知道有沒有人跟我有這樣的疑問,無狀態(tài)組件跟純凈組件有什么不同?這里做一個(gè)區(qū)分:

    無狀態(tài)組件只是作為一個(gè)展示組件,它的好處是:

    易復(fù)用,易測試

    與邏輯處理數(shù)據(jù)解耦,一般來說,app里有越多無狀態(tài)組件越好,這說明邏輯處理都在上層,例如redux 中處理,這樣可以在不渲染的前提下,測數(shù)據(jù)邏輯。

    壞處:

    沒有生命周期,沒辦法用shouldComponentUpdate阻止重新渲染,這也就是說,它沒有幫助我們提高性能的作用,這也是它跟PureComponent最大的不同。

    關(guān)于如何在實(shí)際中使用這兩個(gè)組件,還要根據(jù)具體的實(shí)際情況來選擇~

    總結(jié)

    綜上可以看出,減少不必要的重新渲染對(duì)于提升我們的性能有很大的意義。我個(gè)人覺得,在實(shí)際中,用Perf跟why-did-you-update兩個(gè)工具已經(jīng)可以很好幫我們判斷哪部分不需要重新渲染,幫助我們做出優(yōu)化。

    遺留點(diǎn)

    PureComponent那么好用,但是使用PureComponent是有條件的呀~

    由于PureComponent只是做了一個(gè)淺比較,所以深層嵌套的對(duì)象跟數(shù)組都是比不出來的,可能會(huì)導(dǎo)致需要渲染的地方?jīng)]有重新渲染的錯(cuò)誤展示。

    那么淺比較又是什么呢?下篇文章我們來繼續(xù)探索

    參考鏈接:

    1、https://60devs.com/pure-compo...

    2、https://engineering.musefind....

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

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

    相關(guān)文章

    • React學(xué)習(xí)之漫談React

      摘要:事件系統(tǒng)合成事件的綁定方式合成事件的實(shí)現(xiàn)機(jī)制事件委派和自動(dòng)綁定。高階組件如果已經(jīng)理解高階函數(shù),那么理解高階組件也很容易的。例如我們常見的方法等都是高階函數(shù)。對(duì)測試群眾來說,從質(zhì)量保證的角度出發(fā),單元測試覆蓋率是 事件系統(tǒng) 合成事件的綁定方式 `Test` 合成事件的實(shí)現(xiàn)機(jī)制:事件委派和自動(dòng)綁定。 React合成事件系統(tǒng)的委托機(jī)制,在合成事件內(nèi)部僅僅是對(duì)最外層的容器進(jìn)行了綁定,并且依賴...

      darkbug 評(píng)論0 收藏0
    • 【譯】JavaScript 框架的探索與變遷(下)

      摘要:對(duì)此沒有任何限制,它不關(guān)心這個(gè)。一種控制變化的辦法是不可改變的,持久化的數(shù)據(jù)結(jié)構(gòu)。總結(jié)檢測變化時(shí)開發(fā)中的核心問題,而框架們以各種方式解決這個(gè)問題。因?yàn)榻M件內(nèi)的變化是不被允許的。 AngularJS:臟檢查 我不知道什么更新了,所以當(dāng)更新的時(shí)候,我只能檢查所有的東西。 AngularJS 類似于 Ember,當(dāng)狀態(tài)改變的時(shí)候,必須人工去處理。但不同的是,AngularJS 從不同的角度來...

      CollinPeng 評(píng)論0 收藏0
    • RN 技術(shù)探索:Hermes Engine 初探

      摘要:原方式中是經(jīng)過壓縮的腳本文件,預(yù)編譯后則是二進(jìn)制文件。兩者影響疊加導(dǎo)致整體減小,包大小得到優(yōu)化。引擎包引擎包官方文檔中對(duì)內(nèi)存區(qū)的描述您的應(yīng)用用于處理代碼和資源如字節(jié)碼已優(yōu)化或已編譯的碼庫和字體的內(nèi)存。本文首發(fā)自普惠出行產(chǎn)品技術(shù) 自從 Google 的 Flutter 發(fā)布之后,F(xiàn)acebook 對(duì) React-Native 的迭代開始快了起來,優(yōu)化 React-Native 的性能表現(xiàn)...

      Cc_2011 評(píng)論0 收藏0
    • 漫談前端性能 突破 React 應(yīng)用瓶頸

      摘要:表示調(diào)用棧在下一將要執(zhí)行的任務(wù)。兩方性能解藥我們一般有兩種方案突破上文提到的瓶頸將耗時(shí)高成本高易阻塞的長任務(wù)切片,分成子任務(wù),并異步執(zhí)行這樣一來,這些子任務(wù)會(huì)在不同的周期執(zhí)行,進(jìn)而主線程就可以在子任務(wù)間隙當(dāng)中執(zhí)行更新操作。 showImg(https://segmentfault.com/img/remote/1460000016008111); 性能一直以來是前端開發(fā)中非常重要的話題...

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

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

    0條評(píng)論

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