亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

文字

在內(nèi)部,React 使用幾種聰明的技術(shù)來(lái)最小化更新 UI 所需的昂貴 DOM 操作的數(shù)量。對(duì)于許多應(yīng)用程序而言,使用 React 將導(dǎo)致快速的用戶界面,而無(wú)需專門針對(duì)性能進(jìn)行優(yōu)化。不過(guò),有幾種方法可以加速您的 React 應(yīng)用程序。

使用生產(chǎn)構(gòu)建

如果您在 React 應(yīng)用程序中進(jìn)行基準(zhǔn)測(cè)試或遇到性能問(wèn)題,請(qǐng)確保您正在使用縮小的生產(chǎn)版本進(jìn)行測(cè)試。

默認(rèn)情況下,React 包含許多有用的警告。這些警告在開(kāi)發(fā)中非常有用。但是,他們會(huì)使React變得越來(lái)越大,所以您應(yīng)該確保在部署應(yīng)用程序時(shí)使用生產(chǎn)版本。

如果您不確定您的構(gòu)建過(guò)程是否設(shè)置正確,可以通過(guò)安裝適用于 Chrome 的 React Developer Tools 進(jìn)行檢查。如果您在生產(chǎn)模式下使用 React 訪問(wèn)網(wǎng)站,該圖標(biāo)將具有黑色背景:

如果您以開(kāi)發(fā)模式訪問(wèn) React 網(wǎng)站,該圖標(biāo)將具有紅色背景:

預(yù)計(jì)在使用應(yīng)用程序時(shí)使用開(kāi)發(fā)模式,在將應(yīng)用程序部署到用戶時(shí)使用生產(chǎn)模式。

您可以在下面找到有關(guān)為您的應(yīng)用生成應(yīng)用的說(shuō)明。

創(chuàng)建 React App

如果您的項(xiàng)目是使用 Create React App 構(gòu)建的,請(qǐng)運(yùn)行:

npm run build

這將在build/您的項(xiàng)目文件夾中創(chuàng)建您的應(yīng)用程序的生產(chǎn)版本。

請(qǐng)記住,這只是在部署到生產(chǎn)之前需要的。對(duì)于正常的開(kāi)發(fā),使用npm start。

單文件構(gòu)建

我們提供 React 和 React DOM 的生產(chǎn)就緒版本作為單個(gè)文件:

<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script><script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

請(qǐng)記住,只有以結(jié)尾的 React 文件.production.min.js適用于生產(chǎn)。

分支

為了最有效的 Brunch 生產(chǎn)版本,安裝uglify-js-brunch插件:

# If you use npm
npm install --save-dev uglify-js-brunch

# If you use Yarn
yarn add --dev uglify-js-brunch

然后,要?jiǎng)?chuàng)建生產(chǎn)版本,請(qǐng)將-p標(biāo)志添加到build命令中:

brunch build -p

請(qǐng)記住,您只需要為生產(chǎn)構(gòu)建執(zhí)行此操作。你不應(yīng)該-p在開(kāi)發(fā)中通過(guò)標(biāo)志或應(yīng)用這個(gè)插件,因?yàn)樗鼤?huì)隱藏有用的 React 警告,并且使構(gòu)建慢得多。

Browserify

對(duì)于最高效的 Browserify 生產(chǎn)版本,安裝一些插件:

# If you use npm
npm install --save-dev envify uglify-js uglifyify 

# If you use Yarn
yarn add --dev envify uglify-js uglifyify

要?jiǎng)?chuàng)建生產(chǎn)版本,請(qǐng)確保您添加這些轉(zhuǎn)換(順序很重要)

  • envify變換確保正確的編譯環(huán)境設(shè)置。使其成為全球(-g)。

  • uglifyify轉(zhuǎn)換消除了開(kāi)發(fā)導(dǎo)入。使它成為全局(-g)。

  • 最后,產(chǎn)生的束被傳送到束縛uglify-js(閱讀為什么)。

例如:

browserify ./index.js \  -g [ envify --NODE_ENV production ] \  -g uglifyify \  | uglifyjs --compress --mangle > ./bundle.js

注意:   包名稱是uglify-js,但它提供的二進(jìn)制文件被調(diào)用uglifyjs。這不是一個(gè)錯(cuò)字。

請(qǐng)記住,您只需要為生產(chǎn)構(gòu)建執(zhí)行此操作。你不應(yīng)該在開(kāi)發(fā)中應(yīng)用這些插件,因?yàn)樗鼈儠?huì)隱藏有用的 React 警告,并使構(gòu)建更慢。

卷起

要獲得最高效的匯總生產(chǎn)版本,請(qǐng)安裝一些插件:

# If you use npm
npm install --save-dev rollup-plugin-commonjs rollup-plugin-replace rollup-plugin-uglify 

# If you use Yarn
yarn add --dev rollup-plugin-commonjs rollup-plugin-replace rollup-plugin-uglify

要?jiǎng)?chuàng)建生產(chǎn)版本,請(qǐng)確保您添加這些插件(該訂單很重要)

  • replace插件確保設(shè)置正確的構(gòu)建環(huán)境。

  • commonjs插件提供對(duì) Rollup 中 CommonJS 的支持。

  • uglify插件壓縮和軋液最終束。

plugins: [  // ...  require('rollup-plugin-replace')({    'process.env.NODE_ENV': JSON.stringify('production')  }),  require('rollup-plugin-commonjs')(),  require('rollup-plugin-uglify')(),  // ...]

有關(guān)完整的設(shè)置示例,請(qǐng)參閱此要點(diǎn)。

請(qǐng)記住,您只需要為生產(chǎn)構(gòu)建執(zhí)行此操作。您不應(yīng)該在開(kāi)發(fā)中將uglify插件或replace插件應(yīng)用于'production'值,因?yàn)樗鼈儠?huì)隱藏有用的 React 警告,并且使構(gòu)建更慢。

WebPack

注意:   如果您使用 Create React App,請(qǐng)按照上述說(shuō)明操作。本節(jié)僅與直接配置 webpack 有關(guān)。

要獲得最高效的 webpack 生產(chǎn)版本,請(qǐng)確保將這些插件包含在您的生產(chǎn)配置中:

new webpack.DefinePlugin({  'process.env.NODE_ENV': JSON.stringify('production')}),new webpack.optimize.UglifyJsPlugin()

你可以在 webpack 文檔中了解更多。

請(qǐng)記住,您只需要為生產(chǎn)構(gòu)建執(zhí)行此操作。你不應(yīng)該在開(kāi)發(fā)中應(yīng)用UglifyJsPlugin或者DefinePlugin具有'production'價(jià)值,因?yàn)樗鼈儠?huì)隱藏有用的React警告,并且使構(gòu)建變得更慢。

使用 Chrome 性能標(biāo)簽分析組件

開(kāi)發(fā)模式中,您可以使用受支持的瀏覽器中的性能工具來(lái)可視化組件的安裝,更新和卸載方式。例如:

在 Chrome 中執(zhí)行此操作:

  1. 在查詢字符串中?react_perf加載您的應(yīng)用程序(例如,http://localhost:3000/?react_perf)。

  1. 打開(kāi) Chrome DevTools 性能選項(xiàng)卡并按下記錄。

  1. 執(zhí)行你想要分析的動(dòng)作。記錄時(shí)間不要超過(guò)20秒,否則 Chrome 可能會(huì)掛起。

  1. 停止錄制。

5. 反應(yīng)事件將被分組在User Timing標(biāo)簽下。

請(qǐng)注意,這些數(shù)字是相對(duì)的,因此組件在生產(chǎn)中會(huì)呈現(xiàn)更快速度 不過(guò),這應(yīng)該有助于您意識(shí)到不相關(guān)的用戶界面被錯(cuò)誤更新的時(shí)間,以及用戶界面更新發(fā)生的頻率和頻率。

目前Chrome,Edge和IE是唯一支持此功能的瀏覽器,但我們使用標(biāo)準(zhǔn)的User Timing API,因此我們希望更多瀏覽器為其增加支持。

避免調(diào)節(jié)

React構(gòu)建并維護(hù)呈現(xiàn)的UI的內(nèi)部表示。它包含從組件返回的React元素。這種表示讓React避免了創(chuàng)建DOM節(jié)點(diǎn)和訪問(wèn)現(xiàn)有的節(jié)點(diǎn),因?yàn)檫@可能比JavaScript對(duì)象上的操作慢。有時(shí)它被稱為“虛擬DOM”,但它在React Native上的工作方式相同。

當(dāng)組件的道具或狀態(tài)發(fā)生變化時(shí),React通過(guò)比較新返回的元素和先前渲染的元素來(lái)決定是否需要實(shí)際的DOM更新。當(dāng)它們不相等時(shí),React將更新DOM。

在某些情況下,您的組件可以通過(guò)重寫生命周期函數(shù)來(lái)加速所有這些,生命周期函數(shù)shouldComponentUpdate在重新呈現(xiàn)過(guò)程開(kāi)始之前觸發(fā)。該函數(shù)的默認(rèn)實(shí)現(xiàn)返回true,使React執(zhí)行更新:

shouldComponentUpdate(nextProps, nextState) {  return true;}

如果你知道,在某些情況下,你的組件并不需要更新,您可以返回falseshouldComponentUpdate而是跳過(guò)整個(gè)渲染過(guò)程,包括調(diào)用render()此組件和下方。

shouldComponentUpdate In Action

這是一個(gè)組件的子樹。對(duì)于每一個(gè),SCU指示shouldComponentUpdate返回的內(nèi)容,并vDOMEq指出呈現(xiàn)的React元素是否相同。最后,圓圈的顏色表示組件是否需要調(diào)和。

由于以C2為基礎(chǔ)的子樹shouldComponentUpdate返回false,因此React不會(huì)嘗試渲染C2,因此甚至不必shouldComponentUpdate在C4和C5上調(diào)用。

對(duì)于C1和C3,shouldComponentUpdate返回true,所以React必須下到葉子并檢查它們。對(duì)于shouldComponentUpdate返回的C6 true,由于渲染的元素不相同,React必須更新DOM。

最后一個(gè)有趣的案例是C8。React必須渲染這個(gè)組件,但是由于它返回的React元素與之前渲染的元素相同,所以它不必更新DOM。

請(qǐng)注意,React只需對(duì)C6進(jìn)行DOM突變,這是不可避免的。對(duì)于C8,它通過(guò)比較渲染的React元素和C2的子樹和C7來(lái)保護(hù),甚至不需要比較我們保存的元素shouldComponentUpdate,render也沒(méi)有調(diào)用。

示例

如果你的組件改變的唯一方式是當(dāng)變量props.colorstate.count變量發(fā)生變化時(shí),你可以shouldComponentUpdate檢查:

class CounterButton extends React.Component {  constructor(props) {    super(props);    
    this.state = {count: 1};  }  shouldComponentUpdate(nextProps, nextState) {    if (this.props.color !== nextProps.color) {      
        return true;    }    if (this.state.count !== nextState.count) {      return true;    }    return false;  }  render() {    <button
      color={this.props.color}
      onClick={() => this.setState(state => ({count: state.count + 1}))}>
      Count: {this.state.count}    </button>  }}

在這段代碼,shouldComponentUpdate只是檢查是否有任何變化props.colorstate.count。如果這些值不會(huì)更改,則組件不會(huì)更新。如果你的組件變得更加復(fù)雜,你可以使用類似的模式在組件的所有字段之間進(jìn)行“淺層比較” props,state以確定組件是否應(yīng)該更新。這種模式很普遍,React提供了一個(gè)幫助器來(lái)使用這個(gè)邏輯 - 只是從中繼承而來(lái)的React.PureComponent。所以這段代碼是一個(gè)簡(jiǎn)單的方法來(lái)實(shí)現(xiàn)同樣的事情:

class CounterButton extends React.PureComponent {  constructor(props) {    super(props);    
    this.state = {count: 1};  }  render() {    <button
      color={this.props.color}
      onClick={() => this.setState(state => ({count: state.count + 1}))}>
      Count: {this.state.count}    </button>  }}

大多數(shù)時(shí)候,你可以使用React.PureComponent而不是寫自己的shouldComponentUpdate。它只是進(jìn)行淺層比較,所以如果道具或狀態(tài)可能以淺層比較錯(cuò)過(guò)的方式進(jìn)行了變異,則不能使用它。

這可能是一個(gè)更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)的問(wèn)題。例如,假設(shè)您希望ListOfWords組件呈現(xiàn)以逗號(hào)分隔的單詞列表,并使用父WordAdder組件通過(guò)單擊按鈕將單詞添加到列表中。此代碼無(wú)法正常工作:

class ListOfWords extends React.PureComponent {  render() {    return <div>{this.props.words.join(',')}</div>;  }}
class WordAdder extends React.Component {  constructor(props) {    super(props);    this.state = {
      words: ['marklar']    };    
      this.handleClick = this.handleClick.bind(this);  }  handleClick() {    // This section is bad style and causes a bug    
      const words = this.state.words;
      words.push('marklar');    
      this.setState({words: words});  }  render() {    return (      
          <div><button onClick={this.handleClick} /><ListOfWords words={this.state.words} /></div>    );  }
          }

問(wèn)題是PureComponent將會(huì)對(duì)舊的和新的值進(jìn)行簡(jiǎn)單的比較this.props.words。由于這段代碼wordshandleClick方法中改變了數(shù)組,所以即使數(shù)組中的實(shí)際字已經(jīng)改變WordAdder,舊的和新的值this.props.words也會(huì)相等。該ListOfWords因此將不再更新,即使它有768,16呈現(xiàn)新詞。

不突變數(shù)據(jù)的力量

避免此問(wèn)題的最簡(jiǎn)單方法是避免將您正在用作道具或狀態(tài)的值進(jìn)行變異。例如,handleClick上面的方法可以使用concatas 重寫:

handleClick() {  this.setState(prevState => ({
    words: prevState.words.concat(['marklar'])  }));}

ES6支持?jǐn)?shù)組的擴(kuò)展語(yǔ)法,這可以使這更容易。如果您正在使用Create React App,則默認(rèn)情況下此語(yǔ)法可用。

handleClick() {  this.setState(prevState => ({
    words: [...prevState.words, 'marklar'],  }));};

您也可以以類似的方式重寫改變對(duì)象以避免突變的代碼。例如,假設(shè)我們有一個(gè)名為object的對(duì)象,colormap并且我們想要編寫一個(gè)更改colormap.right為的函數(shù)'blue'。我們可以寫:

function updateColorMap(colormap) {
  colormap.right = 'blue';}

要寫這個(gè)而不改變?cè)紝?duì)象,我們可以使用Object.assign方法:

function updateColorMap(colormap) {  return Object.assign({}, colormap, {right: 'blue'});}

updateColorMap現(xiàn)在返回一個(gè)新對(duì)象,而不是改變舊對(duì)象。Object.assign在ES6中,需要填充。

JavaScript提議添加對(duì)象傳播屬性,以便更容易更新對(duì)象而無(wú)需進(jìn)行突變:

function updateColorMap(colormap) {  return {...colormap, right: 'blue'};}

如果您使用的是創(chuàng)建React應(yīng)用程序,Object.assign則默認(rèn)情況下都可以使用對(duì)象傳播語(yǔ)法。

使用不可變數(shù)據(jù)結(jié)構(gòu)

Immutable.js是解決這個(gè)問(wèn)題的另一種方法。它提供了通過(guò)結(jié)構(gòu)共享工作的不變的,持久的集合:

  • Immutable:一旦創(chuàng)建,一個(gè)集合不能在另一個(gè)時(shí)間點(diǎn)被修改。

  • Persistent:可以根據(jù)以前的集合和諸如集合之類的變體創(chuàng)建新集合。新集合創(chuàng)建后,原始集合仍然有效。

  • Structural Sharing:使用與原始集合盡可能多的相同結(jié)構(gòu)創(chuàng)建新集合,盡量減少?gòu)?fù)制以提高性能。

不變性使追蹤變化便宜。更改總是會(huì)導(dǎo)致一個(gè)新的對(duì)象,所以我們只需要檢查對(duì)象的引用是否已經(jīng)改變。例如,在這個(gè)常規(guī)的 JavaScript 代碼中:

const x = { foo: 'bar' };const y = x;y.foo = 'baz';x === y; // true

雖然y是編輯過(guò)的,但由于它是對(duì)同一個(gè)對(duì)象的引用,所以x此比較返回true。你可以用 immutable.js 編寫類似的代碼:

const SomeRecord = Immutable.Record({ foo: null });
const x = new SomeRecord({ foo: 'bar' });
const y = x.set('foo', 'baz');const z = x.set('foo', 'bar');
x === y; // falsex === z; // true

在這種情況下,由于在變異時(shí)返回一個(gè)新的引用x,所以我們可以使用引用相等性檢查(x === y)來(lái)驗(yàn)證存儲(chǔ)的新值與存儲(chǔ)在y其中的原始值不同x

另外兩個(gè)可以幫助使用不可變數(shù)據(jù)的庫(kù)是無(wú)縫不可變和不可變的幫助器。

不可變的數(shù)據(jù)結(jié)構(gòu)為您提供了一種便捷的方式來(lái)跟蹤對(duì)象的變化,這是我們需要實(shí)現(xiàn)的shouldComponentUpdate。這通??梢詾槟闾峁┖芎玫男阅芴嵘?。

上一篇: 下一篇: