React?Native性能優(yōu)化紅寶書方案詳解
一、React Native介紹
React Native 是Facebook在React.js Conf2015 推出的開源框架,使用React和應(yīng)用平臺(tái)的原生功能來構(gòu)建 Android 和 iOS 應(yīng)用。通過 React Native,可以使用 JavaScript 來訪問移動(dòng)平臺(tái)的 API,使用 React 組件來描述 UI 的外觀和行為。
JS實(shí)現(xiàn)調(diào)用的能力中間的適配層提供了一些橋接方案

1、RN優(yōu)勢(shì)
1.1 HTML/CSS/JS開發(fā)成本低,用統(tǒng)一的代碼規(guī)范開發(fā)移動(dòng)端程序,不用關(guān)注移動(dòng)端差異
1.2 天然跨平臺(tái),開發(fā)一次,可以生成Android和ios兩個(gè)系統(tǒng)上的APP,這減少了開發(fā)人員需要編寫不同版本的應(yīng)用程序的時(shí)間和工作量。
1.3 無審核熱更新
1.4 可擴(kuò)展
1.5 易學(xué)易用:React Native 基于 React,開發(fā)人員可以使用熟悉的 JavaScript 和 React 組件模型來構(gòu)建應(yīng)用程序,因此很容易學(xué)習(xí)和上手。
RN的本質(zhì)是把中間的這個(gè)橋Bridge給搭好,讓JS和native可以互相調(diào)用。
RN為我們提供了JS的運(yùn)行環(huán)境,所以前端開發(fā)者們只需要關(guān)心如何編寫JS代碼,
畫UI只需要畫到virtual DOM 中,不需要特別關(guān)心具體的平臺(tái)。
至于如何把JS代碼轉(zhuǎn)成native代碼的臟活累活,RN底層全干了
2、RN劣勢(shì)
2.1 不成熟,項(xiàng)目版本更新維護(hù)較頻繁,學(xué)習(xí)成本高,試錯(cuò)成本高,有些問題較少解決方案,開發(fā)進(jìn)度慢
2.2 性能:整體性能仍不如原生
2.3 兼容性:涉及底層的功能,需要針對(duì)Android和ios雙端單獨(dú)開發(fā)
2.4 有限的第三方庫:盡管 React Native 社區(qū)不斷增長(zhǎng),但相對(duì)于其他混合應(yīng)用框架,第三方庫和插件的數(shù)量還是有限的。這可能使開發(fā)人員在某些方面受到限制。
2.5 有些原生功能需要自己實(shí)現(xiàn):雖然 React Native 提供了大量原生組件,但某些原生功能需要開發(fā)人員自己實(shí)現(xiàn),這可能需要額外的時(shí)間和工作量。
3、跨平臺(tái)框架比較
開發(fā)模式 | 原生開發(fā) | 混合開發(fā) | Web開發(fā) |
運(yùn)行環(huán)境 | Android、iOS、Windows | 混合App、 React Native,Weex、Flutter | 瀏覽器、WebView |
編程語言 | Java,Objective-C | JavaScript、Dart | HTML、CSS、JavaScript |
可移植性 | 差 | 一般 | 好 |
開發(fā)速度 | 慢 | 一般 | 快 |
性能 | 快 | 一般 | 慢 |
學(xué)習(xí)成本 | 高 | 一般 | 低 |
4、Hybrid App 優(yōu)勢(shì)
4.1 跨平臺(tái)開發(fā)
4.2 離線訪問
4.3 原生應(yīng)用程序的用戶體驗(yàn)
4.4 快速開發(fā)和迭代
混合應(yīng)用程序結(jié)合了Web應(yīng)用程序和本地應(yīng)用程序的優(yōu)點(diǎn),既能夠在原生應(yīng)用程序環(huán)境中運(yùn)行,也能夠在 Web 瀏覽器中運(yùn)行,并且具有更好的用戶體驗(yàn)和功能。這種開發(fā)方式可以大大減少開發(fā)時(shí)間和成本,提高開發(fā)效率。
5、React Native 0.68之前的架構(gòu)

5.1、整體UI渲染太過于依賴JsBridge,容易出現(xiàn)阻塞影響整體UI體驗(yàn)
5.2、性能和問題反饋?zhàn)畲蟮慕M件:
ScrollView:一次渲染不做任何回收,啟動(dòng)性能慢,占用內(nèi)存大
FlatList:做了組件回收,快速滑動(dòng)中容易出現(xiàn)白屏和卡頓
Shadow層最終呈現(xiàn)到原生的UI是異步的,滑動(dòng)太快會(huì)有大量的UI
5.3、事件阻塞在JsBridge,導(dǎo)致了長(zhǎng)時(shí)間白屏的出現(xiàn)
6、RN中的視圖渲染
javascript:JS代碼的執(zhí)行線程,將源碼通過Metro打包后傳給JS引擎進(jìn)行解析:
結(jié)構(gòu) 樣式 屬性
Main線程(UI線程或原生線程):主要負(fù)責(zé)原生渲染(Native UI)和調(diào)用原生模塊(Native Modules Shadow 線程Layout線程:創(chuàng)建Shadow Tree來模擬Reac結(jié)構(gòu)樹(類似虛擬DOM),再由Yoga引擎將Flexbox等樣式,解析成平臺(tái)的布局方式:
寬高 位置
7、RN架構(gòu)設(shè)計(jì)--新舊架構(gòu)對(duì)比

7.1、JavaScript層:
支持React 16+新特性
增強(qiáng)JS靜態(tài)類型檢查(CodeGen)
引入JSI允許替換不同的JavaScript引擎
7.2、Bridge層:
劃分了Fabric和TurboModules,分別負(fù)責(zé)管理UI和Native模塊
7.3、Native層:
精簡(jiǎn)核心模塊,將非核心部分拆除去,作為社區(qū)模塊,獨(dú)立維護(hù)
8、從 0.68 版本開始React Native 的新架構(gòu)
8.1、JSI (JavaScript Interface)
一個(gè)用 C++ 寫成的輕量級(jí)框架
實(shí)現(xiàn)JS引擎的互換
通過JS直接調(diào)用Native
減少不必要的線程通信,省去序列化和反序列化的成本,
減輕了通信壓力,提高了通信性能
8.2、CodeGen
FaceBook推出的代碼生成工具
加入了類型約束后,減少了數(shù)據(jù)類型錯(cuò)誤
自動(dòng)將 Flow 或 TS 有靜態(tài)類型檢查的 JS 代碼轉(zhuǎn)換為 Fabric 和 TurboModules 使用的原生代碼
8.3、優(yōu)化Bridge層
Fabric是整個(gè)框架中的新UI層,簡(jiǎn)化了之前的渲染
Turbo Modules通過JSI可以讓JS直接調(diào)用Native模塊,實(shí)現(xiàn)同步操作,實(shí)現(xiàn)Native模塊按需加載,減少啟動(dòng)時(shí)間,提高性能
8.4、精簡(jiǎn)核心代碼(LEAN Core)
將React Native核心包進(jìn)行瘦身,非必要包移到社區(qū)單獨(dú)維護(hù)
9、React介紹
Facebook,Learn Once,write anywhere
數(shù)據(jù)驅(qū)動(dòng),狀態(tài)決定界面的變化,虛擬dom(抽象層)
虛擬dom的好處,首先是性能的優(yōu)化,不直接操作Dom先進(jìn)行一些比較,計(jì)算找出需要變化的部分,在實(shí)際的dom中進(jìn)行操作
其次,這個(gè)抽象層,還提供了邏輯代碼跨平臺(tái)移植的可能性
虛擬dom的下方對(duì)接的,是網(wǎng)頁,是移動(dòng)端,是電視端,任何一個(gè)可以渲染的端,都可以做接口的適配,使得代碼在任何地方使用
主要四個(gè)部分:
組件:類組件、函數(shù)式組件
屬性Props
狀態(tài)State
jsx:React 和 React Native 都使用JSX 語法,這種語法使得你可以在 JavaScript 中直接輸出本質(zhì)上也就是 JavaScript,所以你可以在其中直接使用變量元素,JSX
hook api: todo補(bǔ)充
生命周期: todo補(bǔ)充
二、性能優(yōu)化點(diǎn)
1、RN加載的主要時(shí)間消耗
todo:補(bǔ)充
2、RN性能優(yōu)化-拆包、分包
React Native 頁面的 JavaScript 代碼包是熱更新平臺(tái)根據(jù)版本號(hào)進(jìn)行下發(fā)的,每次有業(yè)務(wù)改動(dòng),我們都需要通過網(wǎng)絡(luò)請(qǐng)求更新代碼包。
因此,我們?cè)趯?duì)JavaScript 代碼進(jìn)行打包的時(shí)候,需要將包拆分成兩個(gè)部分:
2.1、Common 部分,也就是 React Native 源碼部分;
2.2、業(yè)務(wù)代碼部分,也就是我們需要?jiǎng)討B(tài)下載的部分
具體操作:
JavaScript 代碼包中 React Native 源碼相關(guān)的部分是不會(huì)發(fā)生變化的,所以我們不需要在每次業(yè)務(wù)包更新的時(shí)候都進(jìn)行下發(fā),在工程中內(nèi)置一份就好了。Common 包內(nèi)置到工程中業(yè)務(wù)代碼包進(jìn)行動(dòng)態(tài)下載利用 JSContext 環(huán)境,在進(jìn)入載體頁后在環(huán)境中先加載 Common 包,再加載業(yè)務(wù)代碼包就可以完整的渲染出 React Native 頁面
todo:代碼示例?
3、首屏渲染
通過拆包的方案,已經(jīng)減少了動(dòng)態(tài)下載的業(yè)務(wù)代碼包的大小。但是還會(huì)存在部分業(yè)務(wù)非常龐大,拆包后業(yè)務(wù)代碼包的大小依然很大的情況,依然會(huì)導(dǎo)致下載速度較慢,并且還會(huì)受網(wǎng)絡(luò)情況的影響。
因此,我們可以再次針對(duì)業(yè)務(wù)代碼包進(jìn)行拆分
將一個(gè)業(yè)務(wù)代碼包拆分為一個(gè)主包和多個(gè)子包的方式
在進(jìn)入頁面后優(yōu)先請(qǐng)求主包的 JavaScript 代碼資源,能夠快速地渲染首屏頁面,
緊接著用戶點(diǎn)擊某一個(gè)模塊時(shí),再繼續(xù)下載對(duì)應(yīng)模塊的代碼包并進(jìn)行渲染,就能再進(jìn)一步減少加載時(shí)間。
4、減少渲染的節(jié)點(diǎn)-通過組件懶加載提高應(yīng)用性能
組件懶加載可以讓 react 應(yīng)用在真正需要展示這個(gè)組件的時(shí)候再去展示,有效的減少渲染的節(jié)點(diǎn)數(shù),提高頁面的加載速度
React 官方在 16.6 版本后引入了新的特性:React.lazy 和 React.Suspense,這兩個(gè)組件的配合使用可以比較方便進(jìn)行組件懶加載的實(shí)現(xiàn)
React.lazy 該方法主要的作用就是可以定義一個(gè)動(dòng)態(tài)加載的組件,這可以直接縮減打包后 bundle 的體積,
并且可以延遲加載在初次渲染時(shí)不需要渲染的組件
Suspense組件中的 fallback 屬性接受任何在組件加載過程中你想展示的 React 元素。
你可以將 Suspense 組件置于懶加載組件之上的任何位置,你甚至可以用一個(gè) Suspense 組件包裹多個(gè)懶加載組件。 代碼示例如下:
import React, {Suspense} from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent));
const AnotherComponent = React.lazy(() => import('./AnotherComponent));
function MyComponent() {
return(
<div>
<Suspense fallback={<div> loading...</div>}>
<section>
<OtherComponent/>
<AnotherComponent/>
</section>
</Suspense>
</div>
)
}使用懶加載可以減少bundle文件大小,
不同的文件打包到不同的頁面組件當(dāng)中,加快組件的呈現(xiàn)
import React, {lazy, Suspense} from 'react';
const OtherComponentLazy = lazy(() => import('./OtherComponent));
const AnotherComponentLazy = lazy(() => import('./AnotherComponent));
function Suspensed(lazyComponent) {
return (props) {
<Suspense fallback={<div></div>}>
<lazyComponent {...props} />
</Suspense>
}
}
export const OtherComponent = Suspensed(OtherComponentLazy)
export const AnotherComponent = Suspensed(AnotherComponentLazy)5、提交階段優(yōu)化-避免重復(fù)無限渲染

當(dāng)應(yīng)用程序狀態(tài)發(fā)生更改時(shí),React會(huì)調(diào)用render方法。
如果在render方法中繼續(xù)更改應(yīng)用程序狀態(tài),就會(huì)發(fā)生render方法遞歸調(diào)用,導(dǎo)致應(yīng)用報(bào)錯(cuò)。
Render方法應(yīng)該作為純函數(shù),render方法的執(zhí)行要根據(jù)狀態(tài)的改變,保持組件的行為和渲染方法一致。
執(zhí)行提交階段鉤子,會(huì)阻塞瀏覽器更新頁面。
如果在提交階段鉤子函數(shù)中更新組件 State,會(huì)再次觸發(fā)組件的更新流程,造成兩倍耗時(shí)。
一般在提交階段的鉤子中更新組件狀態(tài)的場(chǎng)景有:
- 類組件應(yīng)使用 getDerivedStateFromProps 鉤子方法代替,函數(shù)組件應(yīng)使用函數(shù)調(diào)用時(shí)執(zhí)行 setState的方式代替。
- 使用上面兩種方式后,React 會(huì)將新狀態(tài)和派生狀態(tài)在一次更新內(nèi)完成。
- 根據(jù) DOM 信息,修改組件狀態(tài)。在該場(chǎng)景中,除非想辦法不依賴 DOM 信息,否則兩次更新過程是少不了的,就只能用其他優(yōu)化技巧了。
6、組件卸載前執(zhí)行清理操作
React 組件性能優(yōu)化的核心是減少渲染真實(shí)DOM節(jié)點(diǎn)的頻率,減少Virtual DOM 比對(duì)的頻率
在組件中為window注冊(cè)的全局事件,以及定時(shí)器,在組件卸載前要清理掉,防止組件卸載后繼續(xù)執(zhí)行影響應(yīng)用性能
import React,{
Component
} from 'react';
export default class Hello extends Component {
componentDidMount() {
this.timer = setTimeout(
() => { console.log('把一個(gè)定時(shí)器的引用掛在this上'); },
500
);
}
componentWillUnmount() {
// 如果存在this.timer,則使用clearTimeout清空。
// 如果你使用多個(gè)timer,那么用多個(gè)變量,或者用個(gè)數(shù)組來保存引用,然后逐個(gè)clear
this.timer && clearTimeout(this.timer);
}
};7、通過使用占位符標(biāo)記提升React組件的渲染性能
使用Fragment不對(duì)應(yīng)具體的視圖,減少了包含的額外標(biāo)記的數(shù)量
僅僅是代表可以包裝而已,跟空的標(biāo)識(shí)符一樣,視圖層級(jí)關(guān)系減少有利于視圖渲染,
滿足在組件頂級(jí)具有單個(gè)父級(jí)的條件
<div> ... </div> // 上面會(huì)多出一個(gè)無意義標(biāo)記 // 應(yīng)該改為 <fragment> ... </fragment> // 或者寫成下面這樣也是可以的 <> ... </>
8、縮小狀態(tài)影響范圍-狀態(tài)下放到使用組件的內(nèi)部
React不直接操作DOM,它在內(nèi)存中維護(hù)一個(gè)快速響應(yīng)的DOM描述,render方法返回一個(gè)DOM的描述
React能夠計(jì)算出兩個(gè)DOM描述的差異,然后更新瀏覽器中的DOM,這就是著名的DOM Diff。
就是說React在接收到屬性(props)或者狀態(tài)(state)更新時(shí),就會(huì)通過前面的方式更新UI。所以React整個(gè)UI渲染是比較快的。但是這里面可能出現(xiàn)的問題是:
假設(shè)我們定義一個(gè)父組件,其包含了5000個(gè)子組件。我們有一個(gè)輸入框輸入操作,每次輸入一個(gè)數(shù)字,對(duì)應(yīng)的那個(gè)子組件背景色變紅。
父組件更新默認(rèn)觸發(fā)所有子組件更新,子組件的props為空對(duì)象,{} === {} 永遠(yuǎn)會(huì)返回false
優(yōu)化思想:將變的和不變的分開(state,props,context)
我們需要先手動(dòng)創(chuàng)建一個(gè)有嚴(yán)重渲染性能的組件,如下所示:
import { useState } from 'react';
export default function App() {
let [color, setColor] = useState('red');
return (
<div>
<input value={color} onChange={(e) => setColor(e.target.value)} />
<p style={{ color }}>Hello, world!</p>
<ExpensiveTree />
</div>
);
}
function ExpensiveTree() {
let now = performance.now();
while (performance.now() - now < 100) {
// Artificial delay -- do nothing for 100ms
}
return <p>I am a very slow component tree.</p>;
}很顯然,當(dāng) App 組件內(nèi)的狀態(tài)發(fā)生了改變,ExpensiveTree 組件會(huì) re-render, 事實(shí)上 ExpensiveTree 組件的 props、state 并未發(fā)生改變,這并不是我們期望的結(jié)果。
export default function App() {
let [color, setColor] = useState('red');
return (
<div>
<input value={color} onChange={(e) => setColor(e.target.value)} />
<p style={{ color }}>Hello, world!</p>
<ExpensiveTree />
</div>
);
}我們可以看到以上 ExpensiveTree 組件并不依賴 App 組件內(nèi)部的狀態(tài),因此我們是否可以考慮,將依賴 color 的元素抽離到一個(gè)依賴 color 的組件中呢?
export default function App() {
return (
<>
<Form />
<ExpensiveTree />
</>
);
}
function Form() {
let [color, setColor] = useState('red');
return (
<>
<input value={color} onChange={(e) => setColor(e.target.value)} />
<p style={{ color }}>Hello, world!</p>
</>
);
}此時(shí),將依賴 color 的元素提取到了 Form 組件中,F(xiàn)orm 組件內(nèi)部的狀態(tài)不再影響 ExpensiveTree 組件的渲染,問題便得到了解決。
9、跳過不必要的組件更新-通過純組件提升性能
- 類組件中使用PureComponent
- 函數(shù)式組件中使用React.memo
在 React 工作流中,如果只有父組件發(fā)生狀態(tài)更新,即使父組件傳給子組件的所有 Props 都沒有修改,也會(huì)引起子組件的 Render 過程。
如果子組件的 Props 和 State 都沒有改變,那么其生成的 DOM 結(jié)構(gòu)和副作用也不應(yīng)該發(fā)生改變。
純組件會(huì)對(duì)組件輸入數(shù)據(jù)進(jìn)行淺層比較,如果當(dāng)前輸入數(shù)據(jù)和上次輸入數(shù)據(jù)相同,組件不會(huì)重新渲染。
比較引用數(shù)據(jù)類型在內(nèi)存中的引用地址是否相同,比較基本數(shù)據(jù)類型的值是否相同
為什么不直接進(jìn)行diff操作?而要先進(jìn)行淺比較?
淺比較只操作當(dāng)前組件的state和props,diff操作會(huì)重新遍歷整個(gè)VirtualDOM樹
10、跳過不必要的組件更新-通過shouldComponentUpdate
純函數(shù)只能進(jìn)行淺層比較,要進(jìn)行深層比較,
使用shouldComponentUpdate,它用于編寫自定義比較邏輯
ShouldComponentUpdate(nextProps,nextState){
if(nextProps……){
return true
}
return false
}11、跳過不必要的組件更新-通過memo純組件提升性能
Memo基本使用:將函數(shù)組件變?yōu)榧兘M件,當(dāng)前props和上一次的props進(jìn)行淺比較,如果相同就阻止組件重新渲染
Memo函數(shù)是淺層數(shù)據(jù)比較,如果遇到引用數(shù)據(jù)類型,需要傳遞自定義比較邏輯,傳給Memo函數(shù)的第二個(gè)參數(shù)
memo的第二個(gè)參數(shù)示例如下:
// 給memo傳遞第二個(gè)參數(shù),自定義比較邏輯
import React, { memo, useEffect, useState } from 'react'
function App () {
const [person, setPerson] = useState({ name: '張三', age: 20, job: 'waiter' })
const [index, setIndex] = useState(0)
useEffect(() => {
let timer = setInterval(() => {
setIndex(prev => prev + 1)
setPerson({ ...person, job: 'chef' })
}, 1000)
return () => {
clearInterval(timer)
}
}, [index, person])
return (
<div>
{index}
<ShowName person={person} />
</div>
)
}
function compare (prevProps, nextProps) {
if (
prevProps.person.name !== nextProps.person.name ||
prevProps.person.age !== nextProps.person.age
) {
return false
}
return true
}
const ShowName = memo(function ({ person }) {
console.log('render...')
return (
<div>
{person.name} {person.age}
</div>
)
}, compare)
export default App12、跳過不必要的組件更新- useMemo、useCallback緩存優(yōu)化
useMemo、useCallback 實(shí)現(xiàn)穩(wěn)定的 Props 值
useMemo 緩存上次計(jì)算的結(jié)果,當(dāng) useMemo 的依賴未發(fā)生改變時(shí),就不會(huì)觸發(fā)重新計(jì)算,一般用在非常耗時(shí)的場(chǎng)景中,
如:遍歷大列表做統(tǒng)計(jì)信息。
useCallback ,將父組件傳遞給子組件時(shí),子組件會(huì)因?yàn)橹匦聄ender發(fā)生改變的時(shí)候,緩存一個(gè)值
useCallback 是 React 的一個(gè) Hook,它用于記住函數(shù)的引用,避免在每次渲染時(shí)都創(chuàng)建一個(gè)新的函數(shù)實(shí)例。這可以幫助優(yōu)化性能,因?yàn)楸苊獠槐匾闹劁秩竞妥咏M件的重新渲染。
使用場(chǎng)景:
當(dāng)你有一個(gè)函數(shù),它依賴于某些 props 或 state,但你不希望它在這些依賴發(fā)生變化時(shí)重新創(chuàng)建,你可以使用 useCallback 來保持引用不變。
如果你有一個(gè)子組件,它是純的(不依賴外部狀態(tài),只依賴于傳入的 props),并且你希望避免非必要的重渲染,你可以使用 useCallback 來保證傳遞給子組件的函數(shù)引用保持不變。
例子代碼:
import React, { useCallback } from 'react';
function ParentComponent() {
const [count, setCount] = useState(0);
// 使用 useCallback 來避免在每次渲染時(shí)都創(chuàng)建一個(gè)新的函數(shù)實(shí)例
const incrementCount = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<div>
<p>Count: {count}</p >
<button onClick={incrementCount}>Increment</button>
ChildComponent onIncrement={incrementCount} />
</div>
);
}
function ChildComponent({ onIncrement }) {
// 這里我們不需要每次 ParentComponent 渲染時(shí)都創(chuàng)建一個(gè)新的函數(shù)實(shí)例
// 因?yàn)?onIncrement 引用沒有變化
return <button onClick={onIncrement}>Increment from Child</button>;
}在這個(gè)例子中,incrementCount 是一個(gè)函數(shù),用于增加計(jì)數(shù)。我們使用 useCallback 來保證在 ParentComponent 的多次渲染中,incrementCount 函數(shù)的引用是不變的,這樣 ChildComponent 就不會(huì)因?yàn)?ParentComponent 的渲染而不必要地重新渲染。
13、列表使用Key屬性
遍歷展示視圖時(shí)使用 key,key 幫助 React 識(shí)別哪些元素改變了,比如被添加或刪除。因此你應(yīng)當(dāng)給數(shù)組中的每一個(gè)元素賦予一個(gè)確定的標(biāo)識(shí)
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}> {number} </li>);使用 key 注意事項(xiàng):
這個(gè)元素在列表中擁有的一個(gè)獨(dú)一無二的字符串。通常,我們使用數(shù)據(jù)中的 id 來作為元素的 key
14、不要使用內(nèi)聯(lián)函數(shù)定義:
如果使用內(nèi)聯(lián)函數(shù),函數(shù)是引用數(shù)據(jù)類型,在內(nèi)存中的地址不會(huì)相同,則每次render函數(shù)時(shí),都會(huì)創(chuàng)建一個(gè)新的函數(shù)實(shí)例
在渲染階段會(huì)綁定新函數(shù)并將舊實(shí)例扔給垃圾回收,因此綁定內(nèi)聯(lián)函數(shù),需要額外的垃圾回收和綁定到DOM的工作
1.Render(){
Return (<input type=“button” onClick={(e)=>{this.setState({inputVal:e.target.value})}}>)
}
2.setNewState=(e)->{this.setState({inputVal:e.target.value})}
//箭頭函數(shù)被添加到類的實(shí)例對(duì)象屬性而不是原型對(duì)象屬性,如果組件被多次重用,每個(gè)實(shí)例都會(huì)有一個(gè)相同的函數(shù)實(shí)例,降低了函數(shù)實(shí)例的可重用性,造成了資源的浪費(fèi)
Render(){
Return (<input type=“button” onClick={(e)=>{this.setNewState}/> )
}
3.Export default class a extends React.Component{
constructor(){
this.handleClick = this.handClick.bind(this)//構(gòu)造函數(shù)只執(zhí)行一次
}
}
handleClick(){xxxxx}
<input type=“button” onClick={this.handleClick}/>
//render方法每次執(zhí)行時(shí)都會(huì)調(diào)用bind方法生成新的函數(shù)實(shí)例
<input type=“button” onClick={this.handleClick.bind(this)}/>15、避免使用內(nèi)聯(lián)樣式
使用內(nèi)聯(lián)樣式時(shí),會(huì)被編譯為JavaScript代碼,JavaScript將樣式規(guī)則映射到元素上,瀏覽器需要花費(fèi)更多時(shí)間處理腳本和渲染UI。
它是在執(zhí)行時(shí)為元素添加樣式,而不是在編譯時(shí)為元素添加樣式。
因此,性能非常的低,更好的辦法是將CSS文件導(dǎo)入組件。能通過css直接做的事情,就不要通過JavaScript去做,因?yàn)镴avaScript操作DOM非常慢
16、事件節(jié)流和防抖
利用debounce、throttle 避免重復(fù)回調(diào)
節(jié)流:
意味著不會(huì)立即執(zhí)行,在觸發(fā)事件之前會(huì)加上幾毫秒延遲,
throttle 更適合需要實(shí)時(shí)響應(yīng)用戶的場(chǎng)景中更適合,
如通過拖拽調(diào)整尺寸或通過拖拽進(jìn)行放大縮?。ㄈ纾簑indow 的 resize 事件)。實(shí)時(shí)響應(yīng)用戶操作場(chǎng)景中,如果回調(diào)耗時(shí)小,
甚至可以用 requestAnimationFrame 代替 throttle。
頁面滾動(dòng)到底部的時(shí)候,使用節(jié)流,否則觸發(fā)多個(gè)網(wǎng)絡(luò)請(qǐng)求調(diào)用,導(dǎo)致性能問題
防抖:
在輸入框中鍵入數(shù)據(jù),直到用戶不再輸入數(shù)據(jù)為止,兼容網(wǎng)絡(luò)調(diào)用提升性能
在搜索場(chǎng)景中,只需響應(yīng)用戶最后一次輸入,無需響應(yīng)用戶的中間輸入值,
debounce 更適合使用在該場(chǎng)景中。
到此這篇關(guān)于React Native性能優(yōu)化紅寶書的文章就介紹到這了,更多相關(guān)React Native性能優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react路由跳轉(zhuǎn)傳參刷新頁面后參數(shù)丟失的解決
這篇文章主要介紹了react路由跳轉(zhuǎn)傳參刷新頁面后參數(shù)丟失的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
深入了解響應(yīng)式React Native Echarts組件
近年來,隨著移動(dòng)端對(duì)數(shù)據(jù)可視化的要求越來越高,通過 WebView 在移動(dòng)端使用 Echarts 這樣功能強(qiáng)大的前端數(shù)據(jù)可視化庫,是解決問題的好辦法。下面就和小編來一起學(xué)習(xí)一下吧2019-05-05
詳解React中的useMemo和useCallback的區(qū)別
React中的useMemo和useCallback是兩個(gè)重要的Hooks。常常被用于優(yōu)化組件的性能。雖然這兩個(gè)Hooks看起來很相似,但它們彼此之間還是有很大的區(qū)別的,隨著小編一起來學(xué)習(xí)吧2023-04-04
React中的Context應(yīng)用場(chǎng)景分析
這篇文章主要介紹了React中的Context應(yīng)用場(chǎng)景分析,Context 提供了一種在組件之間共享數(shù)據(jù)的方式,而不必顯式地通過組件樹的逐層傳遞 props,通過實(shí)例代碼給大家介紹使用步驟,感興趣的朋友跟隨小編一起看看吧2021-06-06
React報(bào)錯(cuò)信息之Expected?an?assignment?or?function?call?and?
這篇文章主要介紹了React報(bào)錯(cuò)之Expected?an?assignment?or?function?call?and?instead?saw?an?expression,下面有兩個(gè)示例來展示錯(cuò)誤是如何產(chǎn)生的,需要的朋友可以參考下2022-08-08
react+ts實(shí)現(xiàn)簡(jiǎn)單jira項(xiàng)目的最佳實(shí)踐記錄
這篇文章主要介紹了react+ts實(shí)現(xiàn)簡(jiǎn)單jira項(xiàng)目,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-07-07

