react-native官方開發文檔

將文檔重點標記出來,其餘的內容到用的時候再去查。javascript

 

View屬性css

enum('flex-start', 'flex-end', 'center', 'stretch', 'space-between', 'space-around')html

align-items屬性適用於全部的flex容器,它是用來設置每一個flex元素在側軸上的默認對齊方式。 align-items和align-content有相同的功能,不過不一樣點是它是用來讓每個單行的容器居中而不是讓整個容器居中。alignItems單行alignContent多行java

alignItems決定其子元素沿着次軸(與主軸垂直的軸,好比若主軸方向爲row,則次軸方向爲column)的排列方式node

align-items:center 沒有效果react

align-content:center 容器中多行全部內容都居中了android

  • justifyContent 內容對齊,FlexBox主軸方向上的排列方式
    enum('flex-start', 'flex-end', 'center', 'space-between', 'space-around', 'space-evenly')

在 React Native 中flex的表現和 CSS 有些區別。flex在 RN 中只能爲整數值,其具體表現請參考yoga佈局引擎的文檔,其地址爲https://github.com/facebook/yogaios

flex爲一個正整數時,組件尺寸會具備彈性,並根據具體的 flex 值來按比例分配。好比兩個組件在同一個父容器中,一個flex爲 2,另外一個flex爲 1,則二者的尺寸比爲 2:1。css3

flex爲 0 時,組件尺寸由widthheight決定,此時再也不具備彈性。git

flex爲-1 時,組件尺寸通常仍是由widthheight決定。可是當空間不夠時,組件尺寸會收縮到minWidthminHeight所設定的值。

flexGrowflexShrinkflexBasis和在 CSS 上表現一致。

主容器的成員從左到右橫向佈局,而非默認的從上到下縱向佈局

enum('row', 'row-reverse', 'column', 'column-reverse')

enum('absolute', 'relative')

transform([{ rotateX: '45deg' }, { rotateZ: '0.785398rad' }])

object: {perspective: number}, ,

object: {rotate: string}, ,

object: {rotateX: string}, ,

object: {rotateY: string}, ,

object: {rotateZ: string}, ,

object: {scale: number}, ,

object: {scaleX: number}, ,

object: {scaleY: number}, ,

object: {translateX: number}, ,

object: {translateY: number}, ,

object: {skewX: string}, ,

object: {skewY: string}

 

 

 

Text屬性(繼承View)

head  "...efg"

middle  "ab...yz"

tail "abcd..."

clip  "abc"

textShadowOffset: object: {width: number,height: number}

colorcolor

fontSize: number

fontStyle: enum('normal', 'italic')

fontWeight: enum('normal', 'bold', '100', '900')

lineHeight: number

textAlign: enum('auto', 'left', 'right', 'center', 'justify')
textDecorationLine: enum('none', 'underline', 'line-through', 'underline line-through')

textShadowColorcolor

fontFamily: string

textShadowRadius: number

includeFontPadding: bool (Android)
Android在默認狀況下會爲文字額外保留一些padding,以便留出空間擺放上標或是下標的文字。對於某些字體來講,這些額外的padding可能會致使文字難以垂直居中。若是你把
textAlignVertical設置爲center以後,文字看起來依然不在正中間,那麼能夠嘗試將本屬性設置爲false。默認值爲true。

textAlignVertical: enum('auto', 'top', 'bottom', 'center') (Android)

letterSpacing: number 字母間距 default is 0

textDecorationColorcolor (iOS)

textDecorationStyle: enum('solid', 'double', 'dotted', 'dashed') (iOS)

textTransform: enum('none', 'uppercase', 'lowercase', 'capitalize')

writingDirection: enum('auto', 'ltr', 'rtl') (iOS)

 

  • testID 用來在端到端測試中定位此視圖
  • selectionColor highlight color of the text (Android)
  • adjustsFontSizeToFit  (iOS) 指定字體是否隨着給定樣式的限制而自動縮放fontFamily
  • minimumFontScale  (iOS) 當adjustsFontSizeToFit開啓時,指定最小的縮放比 0.5

 

 

 

 

TextInput

<TextInput placeholder="placeholder" onChangeText={(text) => this.setState({text})}/>

react 中的 onChange 對應的是 rn 中的 onChangeText,onSubmitEditing會在文本被提交後(用戶按下軟鍵盤上的提交鍵)調用

TextInput在安卓上默認有一個底邊框,同時會有一些padding。若是要想使其看起來和iOS上儘可能一致,則須要設置padding: 0

又又,在安卓上長按選擇文本會致使windowSoftInputMode設置變爲adjustResize,這樣可能致使絕對定位的元素被鍵盤給頂起來。要解決這一問題你須要在AndroidManifest.xml中明確指定合適的windowSoftInputModehttps://developer.android.com/guide/topics/manifest/activity-element.html )值,或是本身監聽事件來處理佈局變化。

在大多數狀況下,咱們推薦使用 受控組件 來實現表單。 在受控組件中,表單數據由 React 組件處理。若是讓表單數據由 DOM 處理時,替代方案爲使用非受控組件

屬性說明

若是爲true,在componentDidMount後會得到焦點(becomeFirstResponder

enum('never', 'while-editing', 'unless-editing', 'always')

是否要在文本框右側顯示「清除」按鈕。僅在單行模式下可用。默認值爲never

若是爲true,每次開始輸入的時候都會清除文本框的內容。

設置 text input 內能被轉化爲可點擊URL的數據的類型。當且僅當multiline={true}editable={false}時起做用。默認狀況下不檢測任何數據類型可接受一個類型值或類型值數組。

dataDetectorTypes的可用值有:

  • 'phoneNumber'
  • 'link'
  • 'address'
  • 'calendarEvent'
  • 'none'
  • 'all'

若是爲true,鍵盤會在文本框內沒有文字的時候禁用確認按鈕。默認值爲false。

圖片必須放置在/android/app/src/main/res/drawable目錄下

<TextInput inlineImageLeft='search_icon' />

指定鍵盤的顏色 iOS enum('default', 'light', 'dark')

決定彈出何種軟鍵盤類型,譬如numeric(純數字鍵盤)。

See screenshots of all the types here.

這些值在全部平臺均可用:

  • default
  • number-pad
  • decimal-pad
  • numeric
  • email-address
  • phone-pad

下面的值僅iOS可用:

  • ascii-capable
  • numbers-and-punctuation
  • url
  • name-phone-pad
  • twitter
  • web-search

下面的值僅Android可用:

  • visible-password

React中原生事件{ nativeEvent: { eventCount, target, text} },ReactNative中是onChangeText

當文本框內容變化時調用此回調函數,改變後的文字內容會做爲參數傳遞

獲取 { nativeEvent: { target } }

回調參數 { nativeEvent: { key: keyValue } }

當組件加載或者佈局變化的時候調用{ nativeEvent: {layout: {x, y, width, height}, target } }

-> scrollViewDidScroll { nativeEvent: { contentOffset: { x, y } } }

{ nativeEvent: { selection: { start, end } } }

此回調函數當軟鍵盤的肯定/提交按鈕被按下的時候調用此函數。若是multiline={true},此屬性不可用

決定「肯定」按鈕顯示的內容。在Android上你還可使用returnKeyLabel

下列這些選項是跨平臺可用的:

  • done
  • go
  • next
  • search
  • send

下列這些選項僅Android可用:

  • none
  • previous

下列這些選項僅iOS可用:

  • default
  • emergency-call
  • google
  • join
  • route
  • yahoo

文本框中的文字內容。 TextInput是一個受約束的(Controlled)的組件,意味着若是提供了value屬性,原生值會被強制與value屬性保持一致。在大部分狀況下這都工做的很好,不過有些狀況下會致使一些閃爍現象——一個常見的緣由就是經過不改變value來阻止用戶進行編輯。若是你但願阻止用戶輸入,能夠考慮設置editable={false};若是你是但願限制輸入的長度,能夠考慮設置maxLength屬性,這兩個屬性都不會致使閃爍。

方法

  • clear()
  • isFocused()

 

 

 

 

Button

通常用TouchableOpacity定製button,視頻教程如何製做一個按鈕講述了完整的過程,或 github.com 搜索 'react native button'

 

 

 

 

 

Picker

<Picker selectedValue={this.state.language}

style={{ height: 50, width: 100 }}

onValueChange={(itemValue, itemIndex) => this.setState({language: itemValue})}>

<Picker.Item label="Java" value="java" />

<Picker.Item label="JavaScript" value="js" />

</Picker>

 

'dialog': 顯示一個模態對話框。默認選項。

'dropdown': 以選擇器所在位置爲錨點展開一個下拉框。

對話框標題

 

 

 

Slider

 

 

 

 

Switch

受控組件 你必須使用onValueChange回調來更新value屬性以響應用戶的操做

 

 

 

 

 

Touchable 系列組件

這個組件的樣式是固定的。因此若是它的外觀並不怎麼搭配你的設計,那就須要使用TouchableOpacity或是TouchableNativeFeedback組件來定製本身所須要的按鈕,視頻教程如何製做一個按鈕講述了完整的過程。或者你也能夠在 github.com 網站上搜索 'react native button' 來看看社區其餘人的做品。

具體使用哪一種組件,取決於你但願給用戶什麼樣的視覺反饋:

  • 通常來講,你可使用TouchableHighlight來製做按鈕或者連接。注意此組件的背景會在用戶手指按下時變暗。
  • 在 Android 上還可使用TouchableNativeFeedback,它會在用戶手指按下時造成相似墨水漣漪的視覺效果。
  • TouchableOpacity會在用戶手指按下時下降按鈕的透明度,而不會改變背景的顏色。

某些場景中你可能須要檢測用戶是否進行了長按操做。能夠在上面列出的任意組件中使用onLongPress屬性來實現。

 

 

 

React Native 提供了幾個適用於展現長列表數據的組件,通常而言咱們會選用FlatList或是SectionList

FlatList組件用於顯示一個垂直的滾動列表,其中的元素之間結構近似而僅數據不一樣。

FlatList更適於長列表數據,且元素個數能夠增刪。和ScrollView不一樣的是,FlatList並不當即渲染全部元素,而是優先渲染屏幕上可見的元素。

FlatList組件必須的兩個屬性是datarenderItemdata是列表的數據源,而renderItem則從數據源中逐個解析數據,而後返回一個設定好格式的組件來渲染。

 

 

 

使用 Fetch

React Native 提供了和 web 標準一致的Fetch API,用於知足開發者訪問網絡的需求。

 

網絡請求自然是一種異步操做(譯註:一樣的還有asyncstorage,請不要再問怎樣把異步變成同步!不管在語法層面怎麼折騰,它們的異步本質是沒法變動的。異步的意思是你應該趁這個時間去作點別的事情,好比顯示 loading,而不是讓界面卡住傻等)。Fetch 方法會返回一個Promise,這種模式能夠簡化異步風格的代碼

 

你也能夠在 React Native 應用中使用 ES2017 標準中的async/await 語法:

 

 

 

 

事件

 

View

做爲建立 UI 時最基礎的組件,View 是一個支持 Flexbox 佈局、樣式、一些觸摸處理、和一些無障礙功能的容器,而且它能夠放到其它的視圖裏,也能夠有任意多個任意類型的子視圖。不論在什麼平臺上,View 都會直接對應一個平臺的原生視圖。

 

合成觸摸事件

用於 View 響應屬性 (例如, onResponderMove), 合成觸摸事件採用如下的格式:

  • nativeEvent
  • changedTouches - 從上一次事件以來的觸摸事件數組。
  • identifier - 觸摸事件的 ID。
  • locationX - 觸摸事件相對元素位置的 X 座標。
  • locationY - 觸摸事件相對元素位置的 Y 座標。
  • pageX - 觸摸事件相對根元素位置的 X 座標。
  • pageY - 觸摸事件相對根元素位置的 Y 座標。
  • target - 接收觸摸事件的元素 ID.
  • timestamp - 觸摸事件的時間標記,用來計算速度.
  • touches - 屏幕上全部當前觸摸事件的數組.

 

查看 Props

設置這個視圖是否要響應 touch start 事件

View.props.onStartShouldSetResponder: (event) => [true | false], 其中 event 是一個合成觸摸事件

當組件掛載或者佈局變化的時候調用,參數爲:{nativeEvent: { layout: {x, y, width, height}}}

這個事件會在佈局計算完成後當即調用一次,不過收到此事件時新的佈局可能尚未在屏幕上呈現,尤爲是一個佈局動畫正在進行中的時候。

若是父視圖想要阻止子視圖響應 touch move 事件時,它就應該設置這個方法並返回true

其餘某個視圖想要成爲事件的響應者,並要求這個視圖放棄對事件的響應時,就會調用這個函數。若是容許釋放響應,就返回true

用於控制當前視圖是否能夠做爲觸控事件的目標。

auto:視圖能夠做爲觸控事件的目標。

none:視圖不能做爲觸控事件的目標。

box-none:視圖自身不能做爲觸控事件的目標,但其子視圖能夠。相似於你在 CSS 中這樣設置:

'box-only':視圖自身能夠做爲觸控事件的目標,但其子視圖不能。相似於你在 CSS 中這樣設置:

例如:.box-none { pointer-events: none; } .box-none * { pointer-events: all; }

決定這個視圖是否要先離屏渲染再進行半透明度處理,來確保顏色和混合效果正確,默認值(false)

 

 

 

 

Image

用於顯示多種不一樣類型圖片的 React 組件,包括網絡圖片、靜態資源、臨時的本地圖片、以及本地磁盤上的圖片(如相冊)等

請注意對於網絡和 base64 數據的圖片須要手動指定尺寸!

在 Android 上支持 GIF 和 WebP 格式圖片

默認狀況下 Android 是不支持 GIF 和 WebP 格式的。你須要在android/app/build.gradle文件中根據須要手動添加如下模塊:

dependencies {
 // 若是你須要支持WebP格式,包括WebP動圖
 
compile 'com.facebook.fresco:animated-webp:1.10.0'
 
compile 'com.facebook.fresco:webpsupport:1.10.0'

}

屬性

overflow: enum('visible', 'hidden')

resizeMode: ImageResizeMode(containcoverstretchcenterrepeat)

overlayColor在不能圓角透明時,設置overlayColor和背景色一致

決定當組件尺寸和圖片尺寸不成比例的時候如何調整圖片的大小。

cover: 等比縮放不留空白,鋪滿屏幕

contain: 等比縮放可能空白

stretch

repeat

center

當圖片實際尺寸和容器樣式尺寸不一致時,決定以怎樣的策略來調整圖片的尺寸。默認爲auto

auto: 使用啓發式算法來在resizescale中自動決定。

resize: 在圖片解碼以前,使用軟件算法對其在內存中的數據進行修改。當圖片尺寸比容器尺寸大得多時,應該優先使用此選項。

scale: 對圖片進行縮放。和resize相比,scale速度更快(通常有硬件加速),並且圖片質量更優。在圖片尺寸比容器尺寸小或者只是稍大一點時,應該優先使用此選項。

關於resizescale的詳細說明請參考http://frescolib.org/docs/resizing.html

  • onProgress {nativeEvent: {loaded, total}} (iOS)

方法

靜態圖片引用語法require('./image.jpg')所返回的資源 id 或是一個ImageSource.

 

 

 

ScrollView

ScrollView必須有一個肯定的高度才能正常工做,由於它實際上所作的就是將一系列不肯定高度的子組件裝進一個肯定高度的容器(經過滾動操做)。通常來講咱們會給ScrollView設置flex: 1以使其自動填充父容器的空餘空間,但前提條件是全部的父容器自己也設置了flex或者指定了高度,不然就會致使沒法正常滾動

屬性

用戶拖拽滾動視圖的時候,是否要隱藏軟鍵盤。

'none' (默認值),拖拽時不隱藏軟鍵盤。

'on-drag',當拖拽開始的時候隱藏軟鍵盤。

'interactive',軟鍵盤伴隨拖拽操做同步地消失,而且若是往上滑動會恢復鍵盤iOS

不少人反應TextInput沒法自動失去焦點/須要點擊屢次切換到其餘組件等等問題,其關鍵都是需要將TextInput放到ScrollView中再設置本屬性

'never' (默認值),點擊TextInput之外的子組件會使當前的軟鍵盤收起。此時子元素不會收到點擊事件。

'always',鍵盤不會自動收起,ScrollView也不會捕捉點擊事件,但子組件能夠捕獲。

'handled',當點擊事件被子組件捕獲時,鍵盤不會自動收起。這樣切換TextInput時鍵盤能夠保持狀態。多數帶有TextInput的狀況下你應該選擇此項。

stickyHeaderIndices={[0]}會讓第一個成員固定在滾動視圖頂端,不能和horizontal={true}一塊兒使用。

默認false,是否水平排列

若是你的ScrollView或FlatList的頭部出現莫名其妙的空白,嘗試將此屬性置爲false

方法

scrollTo({x: 0, y: 0, animated: true})

scrollTo({x: 0, y: 0, duration: 500})

scrollToEnd({animated: boolean, duration: number});

 

 

 

 

 

 

 

FlatList

若是須要分組//區(section),請使用<SectionList>

  • 對於MyListItem組件來講,其onPressItem屬性使用箭頭函數而非 bind 的方式進行綁定,使其不會在每次列表從新 render 時生成一個新的函數,從而保證了 props 的不變性(固然前提是 idselectedtitle也沒變),不會觸發自身無謂的從新 render。換句話說,若是你是用 bind 來綁定onPressItem,每次都會生成一個新的函數,致使 props 在===比較時返回 false,從而觸發自身的一次沒必要要的從新 render。
  • FlatList指定extraData={this.state}屬性,是爲了保證state.selected變化時,可以正確觸發FlatList的更新。若是不指定此屬性,則FlatList不會觸發更新,由於它是一個PureComponent,其 props 在===比較中沒有變化則不會觸發更新。
  • keyExtractor屬性指定使用 id 做爲列表每一項的 key。

 

本組件實質是基於<VirtualizedList>組件的封裝,繼承了其全部 props(也包括全部<ScrollView>)的 props)

注意事項:

  • 當某行滑出渲染區域以外後,其內部狀態將不會保留。請確保你在行組件之外的地方保留了數據。
  • 本組件繼承自PureComponent而非一般的Component,這意味着若是其props淺比較中是相等的,則不會從新渲染。因此請先檢查你的renderItem函數所依賴的props數據(包括data屬性以及可能用到的父組件的 state),若是是一個引用類型(Object 或者數組都是引用類型),則須要先修改其引用地址(好比先複製到一個新的 Object 或者數組中),而後再修改其值,不然界面極可能不會刷新。(譯註:這一段不瞭解的朋友建議先學習下js 中的基本類型和引用類型。)
  • 爲了優化內存佔用同時保持滑動的流暢,列表內容會在屏幕外異步繪製。這意味着若是用戶滑動的速度超過渲染的速度,則會先看到空白的內容。
  • 默認狀況下每行都須要提供一個不重複的 key 屬性。你也能夠提供一個keyExtractor函數來生成 key。

本組件若是嵌套在其餘同滾動方向的 FlatList 中,則不會繼承ScrollView 的 Props

屬性

可選的優化,用於避免動態測量內容尺寸的開銷,不過前提是你能夠提早知道內容的高度

  getItemLayout={(data, index) => (
    {
length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
  )}

方法

 

 

 

 

ActionSheetIOS

static showActionSheetWithOptions(options, callback)

options (字符串數組) - 一組按鈕的文字(必選)

cancelButtonIndex (整型) - 取消性質的按鈕在options中的位置(索引)

destructiveButtonIndex (整型) - 刪除性質的按鈕在options中的位置(索引)

title (字符串) - 彈出框頂部的標題

message (字符串) - 彈出框頂部標題下方的信息

 

static showShareActionSheetWithOptions(options, failureCallback, successCallback)

 

 

 

AlertIOS

AlertIOS.alert( '舒適提示', '您的話費餘額不足請充值.' );

 

 

 

 

DatePickerIOS

 

 

 

 

ImagePickerIOS

方法

 

 

 

native-navigation

react-native-navigation

咱們推薦使用跨平臺的react-navigation中的 DrawerNavigation 來代替此組件。

 

 

PushNotificationIOS

本模塊幫助你處理應用的推送通知,包括權限控制以及應用圖標上的角標數(未讀消息數)。

要使用推送通知功能,首先在蘋果後臺配置推送通知服務而且準備好服務端的系統。

首先請手動連接PushNotificationIOS的庫:

  • node_modules/react-native/Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj文件拖到Xcode界面中
  • 在Xcode的Link Binary With Libraries中添加libRCTPushNotification.a

而後你須要在AppDelegate中啓用推送通知的支持以及註冊相應的事件。

查看方法

 

 

 

BackHandler

Android:監聽後退按鈕事件。若是沒有添加任何監聽函數,或者全部的監聽函數都返回 false,則會執行默認行爲,退出應用。

方法

 

 

 

DatePickerAndroid

 

 

PermissionsAndroid

PermissionsAndroid 能夠訪問Android M(也就是6.0)開始提供的權限模型。有一些權限寫在AndroidManifest.xml就能夠在安裝時自動得到,但有一些「危險」的權限則須要彈出提示框供用戶選擇。本API即用於後一種情形。

在低於Android 6.0的設備上,權限只要寫在AndroidManifest.xml裏就會自動得到,此情形下check會始終返回true和而request方法將始終解析爲PermissionsAndroid.RESULTS.GRANTED

若是用戶以前拒絕過你的某項權限請求,那麼系統會建議你顯示一個爲何須要這個權限的「詳細解釋」(rationale參數)。若是用戶以前拒絕過,那麼當你再次申請的時候,彈出的就可能不是原先的申請信息,而是rationale參數裏提供的進一步解釋。

 

 

須要提示用戶的權限都以常量形式列在PermissionsAndroid.PERMISSIONS中:

  • READ_CALENDAR: 'android.permission.READ_CALENDAR'
  • WRITE_CALENDAR: 'android.permission.WRITE_CALENDAR'
  • CAMERA: 'android.permission.CAMERA'
  • READ_CONTACTS: 'android.permission.READ_CONTACTS'
  • WRITE_CONTACTS: 'android.permission.WRITE_CONTACTS'
  • GET_ACCOUNTS: 'android.permission.GET_ACCOUNTS'
  • ACCESS_FINE_LOCATION: 'android.permission.ACCESS_FINE_LOCATION'
  • ACCESS_COARSE_LOCATION: 'android.permission.ACCESS_COARSE_LOCATION'
  • RECORD_AUDIO: 'android.permission.RECORD_AUDIO'
  • READ_PHONE_STATE: 'android.permission.READ_PHONE_STATE'
  • CALL_PHONE: 'android.permission.CALL_PHONE'
  • READ_CALL_LOG: 'android.permission.READ_CALL_LOG'
  • WRITE_CALL_LOG: 'android.permission.WRITE_CALL_LOG'
  • ADD_VOICEMAIL: 'com.android.voicemail.permission.ADD_VOICEMAIL'
  • USE_SIP: 'android.permission.USE_SIP'
  • PROCESS_OUTGOING_CALLS: 'android.permission.PROCESS_OUTGOING_CALLS'
  • BODY_SENSORS: 'android.permission.BODY_SENSORS'
  • SEND_SMS: 'android.permission.SEND_SMS'
  • RECEIVE_SMS: 'android.permission.RECEIVE_SMS'
  • READ_SMS: 'android.permission.READ_SMS'
  • RECEIVE_WAP_PUSH: 'android.permission.RECEIVE_WAP_PUSH'
  • RECEIVE_MMS: 'android.permission.RECEIVE_MMS'
  • READ_EXTERNAL_STORAGE: 'android.permission.READ_EXTERNAL_STORAGE'
  • WRITE_EXTERNAL_STORAGE: 'android.permission.WRITE_EXTERNAL_STORAGE'

 

返回值都以常量形式記錄在PermissionsAndroid.RESULTS中:

  • GRANTED: 'granted', 表示用戶已受權
  • DENIED: 'denied', 表示用戶已拒絕
  • NEVER_ASK_AGAIN: 'never_ask_again',表示用戶已拒絕,且不肯被再次詢問。

方法

 

 

 

ViewPagerAndroid

一個容許在子視圖之間左右翻頁的容器。每個 ViewPagerAndroid 的子容器會被視做一個單獨的頁,而且會被拉伸填滿 ViewPagerAndroid。全部的子視圖都必須是純 View,而不能是自定義的複合容器。

當在頁間切換時(不管是因爲動畫仍是因爲用戶在頁間滑動/拖拽)執行,event.nativeEvent

position 從左數起第一個當前可見的頁面的下標。

offset 一個在[0,1]以內的範圍(能夠等於0或1),表明當前頁面切換的狀態。值 x 表示如今"position"所表示的頁有(1 - x)的部分可見,而下一頁有 x 的部分可見。

 

 

 

Alert

alert(title, message?, buttons?, options?, type?)

iOS 上你能夠指定任意數量的按鈕。每一個按鈕還均可以指定本身的樣式,此外還能夠指定提示的類別。

Android 上最多能指定三個按鈕,這三個按鈕分別具備中間態消極態積極態的概念。

 

 

 

 

Animated

配置動畫

Animated提供了三種動畫類型。每種動畫類型都提供了特定的函數曲線,用於控制動畫值從初始值變化到最終值的變化過程:

大多數狀況下你應該使用timing()。默認狀況下,它使用對稱的 easeInOut 曲線,將對象逐漸加速到全速,而後經過逐漸減速中止結束。

使用動畫

經過在動畫上調用start()來啓動動畫。 start()須要一個 完成 回調函數,當動畫完成時將會調用它。若是動畫運行正常,則將經過{finished:true}觸發回調。若是動畫是由於調用了stop()而結束(例如,由於它被手勢或其餘動畫中斷),則它會收到{finished:false}

啓用原生動畫驅動

使用原生動畫,咱們會在開始動畫以前將全部關於動畫的內容發送到原生代碼,從而使用原生代碼在 UI 線程上執行動畫,而不是經過對每一幀的橋接去執行動畫。一旦動畫開始,JS 線程就能夠在不影響動畫效果的狀況下阻塞(去執行其餘任務)掉了。

您能夠經過在動畫配置中指定useNativeDriver:true 來使用原生動畫驅動。你能夠在動畫文檔 中看到更詳細的解釋。

自定義動畫組件

組件必須通過特殊處理才能用於動畫。所謂的特殊處理主要是指把動畫值綁定到屬性上,而且在一幀幀執行動畫時避免 react 從新渲染和從新調和的開銷。此外還得在組件卸載時作一些清理工做,使得這些組件在使用時是安全的。

Animated中默認導出瞭如下這些能夠直接使用的動畫組件,固然它們都是經過使用上面這個方法進行了封裝:

  • Animated.Image
  • Animated.ScrollView
  • Animated.Text
  • Animated.View

組合動畫

動畫還可使用組合函數以複雜的方式進行組合:

動畫也能夠經過將toValue設置爲另外一個動畫的Animated.Value來簡單的連接在一塊兒。請參閱動畫指南中的跟蹤動態值值。

默認狀況下,若是一個動畫中止或中斷,則組合中的全部其餘動畫也會中止。

合成動畫值

你可使用加減乘除以及取餘等運算來把兩個動畫值合成爲一個新的動畫值:

插值

interpolate()函數容許輸入範圍映射到不一樣的輸出範圍。默認狀況下,它將推斷超出給定範圍的曲線,但也能夠限制輸出值。它默認使用線性插值,但也支持緩動功能。

你能夠在動畫文檔中瞭解到更多。

處理手勢和其餘事件

手勢,如平移或滾動,以及其餘事件可使用Animated.event()直接映射到動畫值。這是經過結構化映射語法完成的,以即可以從複雜的事件對象中提取值。第一層參數是一個數組,你能夠在其中指定多個參數映射,這種映射能夠是嵌套的對象。

例如,在使用水平滾動手勢時,爲了將event.nativeEvent.contentOffset.x映射到scrollXAnimated.Value),您須要執行如下操做:

 

 

 

 

CameraRoll

CameraRoll模塊提供了訪問本地相冊的功能。在 iOS 上使用這個模塊以前,你須要先連接RCTCameraRoll庫,具體作法請參考連接原生庫文檔。

譯註:本模塊只提供了基本的訪問圖片的功能,並無提供相冊界面。對於多數開發者來講,可能第三方的react-native-image-crop-picker的功能更爲完整易用(可多選、壓縮、裁剪等)。

權限

從 iOS 10 開始,訪問相冊須要用戶受權。你須要在Info.plist中添加一條名爲NSPhotoLibraryUsageDescription的鍵,而後在其值中填寫向用戶請求權限的具體描述。編輯完成後這個鍵在 Xcode 中實際會顯示爲Privacy - Photo Library Usage Description

從 iOS 11 開始,若是須要保存圖片,則須要額外申請用戶受權。你須要在Info.plist中添加一條名爲NSPhotoLibraryAddUsageDescription的鍵,而後在其值中填寫向用戶請求權限的具體描述。編輯完成後這個鍵在 Xcode 中實際會顯示爲Privacy - Photo Library Additions Usage Description。而名爲NSPhotoLibraryUsageDescription的鍵此時僅控制相冊的讀取。具體說明請翻閱官方文檔搜索相關鍵值。

 

 

 

 

Clipboard

Clipboard組件能夠在 iOS Android 的剪貼板中讀寫內容。

 

 

 

 

 

 

 

Dimensions

本模塊用於獲取設備屏幕的寬高。

儘管尺寸信息當即就可用,但它可能會在未來被修改(譬如設備的方向改變),因此基於這些常量的渲染邏輯和樣式應當每次 render 以後都調用此函數,而不是將對應的值保存下來。(舉例來講,你可能須要使用內聯的樣式而不是在StyleSheet中保存相應的尺寸)。

var {height, width} = Dimensions.get('window');

Dimensions.get('screen')

 

 

 

 

 

KeyboardAvoidingView

本組件用於解決一個常見的尷尬問題:手機上彈出的鍵盤經常會擋住當前的視圖。本組件能夠自動根據鍵盤的位置,調整自身的 position 或底部的 padding,以免被遮擋。

 

 

 

 

Linking

僅用在原生代碼的項目

Linking提供了一個通用的接口來與傳入和傳出的 App 連接進行交互。

要了解更多如何在 Android 上支持深度連接的說明,請參閱Enabling Deep Links for App Content - Add Intent Filters for Your Deep Links.若是要在現有的 MainActivity 中監聽傳入的 intent,那麼須要在AndroidManifest.xml中將 MainActivity launchMode設置爲singleTask。相關解釋可參考<activity>文檔。

<activity android:name=".MainActivity" android:launchMode="singleTask">

對於 iOS 來講,若是要在 App 啓動後也監聽傳入的 App 連接,那麼首先須要在項目中連接RCTLinking,具體步驟請參考手動連接這篇文檔,而後須要在AppDelegate.m中增長代碼

 

而後你的 React 組件就能夠監聽Linking的相關事件:

要啓動一個連接相對應的應用(打開瀏覽器、郵箱或者其它的應用),只需調用:

Linking.openURL(url).catch(err => console.error('An error occurred', err));

getInitialURL() 若是應用是被一個連接調起的,則會返回相應的連接地址,不然返回null

 

 

 

 

 

 

Modal

Modal 組件是一種簡單的覆蓋在其餘視圖之上顯示內容的方式。

slide 從底部滑入滑出

fade 淡入淡出

none 沒有動畫,直接蹦出來

 

 

 

 

 

 

PixelRatio

PixelRatio 類提供了訪問設備的像素密度的方法

返回設備的像素密度

PixelRatio.get() === 1

mdpi Android devices

PixelRatio.get() === 1.5

hdpi Android devices

PixelRatio.get() === 2   @2x

iPhone 4, 4S

iPhone 5, 5C, 5S

iPhone 6, 7, 8

xhdpi Android devices

PixelRatio.get() === 3   @3x

iPhone 6 Plus, 7 Plus, 8 Plus

iPhone X, XS, XS Max

Pixel, Pixel 2

xxhdpi Android devices

PixelRatio.get() === 3.5

Nexus 6

Pixel XL, Pixel 2 XL

xxxhdpi Android devices

返回字體大小縮放比例

將一個佈局尺寸(dp)轉換爲像素尺寸(px) 返回一個整數值

 

 

 

 

RefreshControl

這一組件能夠用在ScrollView或FlatList內部,爲其添加下拉刷新的功能。當ScrollView處於豎直方向的起點位置(scrollY: 0),此時下拉會觸發一個onRefresh事件

refreshing是一個受控屬性, 因此必須在onRefresh函數中設置爲true,不然loading指示器會當即中止

 

 

 

 

 

StatusBar

控制應用狀態欄的組件

和導航器一塊兒使用的注意事項

因爲StatusBar能夠在任意視圖中加載,且後加載的設置會覆蓋先前的設置。所以在配合導航器使用時,請務必考慮清楚StatusBar的放置順序。

靜態API

有些場景並不適合使用組件,所以StatusBar也暴露了一個靜態API。然而不推薦你們同時經過靜態API和組件來定義相同的屬性,由於靜態API定義的屬性值在後續的渲染中會被組件中定義的值所覆蓋。

屬性

方法

enum('default', 'light-content', 'dark-content')

查看類型定義

enum('none', 'fade', 'slide')

 

 

 

 

 

WebView

webview已經廢棄請使用:react-native-community/react-native-webview 

設置 js 字符串,在網頁加載以前注入的一段 JS 代碼

在網頁加載完成以後,還能夠主動調用此方法(以 ref 形式調用)繼續給 WebView 注入 JS 代碼。注入後會當即執行

控制是否啓用 JavaScript。僅在安卓下使用,由於 IOS 默認爲啓用 JavaScript。默認值爲true

指定混合內容模式。即 WebView 是否應該容許安全連接(https)頁面中加載非安全連接(http)的內容,

never (默認) - WebView 不容許安全連接頁面中加載非安全連接的內容

always - WebView 容許安全連接頁面中加載非安全連接的內容。

compatibility - WebView 會盡可能和瀏覽器當前對待此狀況的行爲一致

在 webview 內部的網頁中調用 window.postMessage 方法時能夠觸發此屬性對應的函數,從而實現網頁和 RN 之間的數據交換。 設置此屬性的同時會在 webview 中注入一個 postMessage 的全局函數並覆蓋可能已經存在的同名實現。

網頁端的 window.postMessage 只發送一個參數 data,此參數封裝在 RN 端的 event 對象中, event.nativeEvent.data。data 只能是一個字符串。

http:// https://  *

在 WebView 中載入一段靜態的 html 代碼或是一個 url(還能夠附帶一些 header 選項)。注意若是是載入html代碼,則須要設置originWhitelist,好比能夠設爲["*"]來容許運行本地代碼

Load uri

  • uri (string) - {uri: 'https://github.com/facebook/react-native'}
  • method (string) - GET and POST.
  • headers (object) - Additional HTTP headers to send with the request. On Android only GET
  • body (string) - The HTTP body to send with the request. This must be a valid UTF-8 string, and will be sent exactly as specified, with no additional encoding (e.g. URL-escaping or base64) applied. On Android, this can only be used with POST requests.

Static HTML

  • html (string) - A static HTML page to display in the WebView.
  • baseUrl (string) - The base URL to be used for any relative links in the HTML.

設置true的時候會使用新的WKWebView來代替老的UIWebView

方法

 

 

 

 

 

 

特定平臺代碼

React Native 提供了兩種方法來區分平臺:

 

Platform 模塊

Platform.OS iOS 上會返回ios,而在 Android 設備或模擬器上則會返回android

Platform.select()能夠以 Platform.OS key,從傳入的對象中返回對應平臺的值

 

檢測 Android 版本

在 Android 上,Version屬性是一個數字,表示 Android 的 api level:

if (Platform.Version === 25) {
 
  console.log("Running on Nougat!");
}

檢測 iOS 版本

在 iOS 上,Version屬性是-[UIDevice systemVersion]的返回值,具體形式爲一個表示當前系統版本的字符串。好比多是"10.3"

const majorVersionIOS = parseInt(Platform.Version, 10);
if (majorVersionIOS <= 9) {
 
  console.log("Work around a change in behavior");
}

特定平臺擴展名

當不一樣平臺的代碼邏輯較爲複雜時,最好是放到不一樣的文件裏,這時候咱們可使用特定平臺擴展名。React Native 會檢測某個文件是否具備.ios.或是.android.的擴展名,而後根據當前運行的平臺自動加載正確對應的文件。

好比你能夠在項目中建立下面這樣的組件:

BigButton.ios.js
BigButton.android.js

而後去掉平臺擴展名直接引用:

import BigButton from './BigButton';

React Native 會根據運行平臺的不一樣自動引入正確對應的組件

 

若是你還但願在 web 端複用 React Native 的代碼,那麼還可使用.native.js的擴展名。此時 iOS Android 會使用BigButton.native.js文件,而 web 端會使用BigButton.js。(注意目前官方並無直接提供 web 端的支持,請在社區搜索第三方方案)

 

 

 

 

 

 

靜態圖片資源

React Native 提供了一個統一的方式來管理 iOS 和 Android 應用中的圖片。要往 App 中添加一個靜態圖片,只需把圖片文件放在代碼文件夾中某處,而後像下面這樣去引用它:

<Image source={require('./my-icon.png')} />

圖片文件的查找會和 JS 模塊的查找方式同樣。在上面的這個例子裏,是哪一個組件引用了這個圖片,Packager 就會去這個組件所在的文件夾下查找my-icon.png。而且,若是你有my-icon.ios.pngmy-icon.android.png,Packager 就會根據平臺而選擇不一樣的文件。

你還可使用@2x@3x這樣的文件名後綴,來爲不一樣的屏幕精度提供圖片。好比下面這樣的代碼結構:

.
├──
button.js
└──
img
    ├── check
.png
    ├── check@
2x.png
    └── check@
3x.png

而且button.js裏有這樣的代碼:

<Image source={require('./img/check.png')} />

Packager 會打包全部的圖片而且依據屏幕精度提供對應的資源。iPhone 7 會使用check@2x.png,而 iPhone 7 plus 或是 Nexus 5 上則會使用check@3x.png。若是沒有圖片剛好知足屏幕分辨率,則會自動選中最接近的一個圖片。

注意事項:

  • 若是你添加圖片的時候 packager 正在運行,可能須要重啓 packager 以便能正確引入新添加的圖片。
  • 爲了使新的圖片資源機制正常工做,require 中的圖片名字必須是一個靜態字符串(不能使用變量!由於 require 是在編譯時期執行,而非運行時期執行!)
  • 經過這種方式引用的圖片資源包含圖片的尺寸(寬度,高度)信息,若是你須要動態縮放圖片(例如,經過 flex),你可能必須手動在 style 屬性設置{ width: null, height: null }

 

上面描述的require語法也能夠用來靜態地加載你項目中的聲音、視頻或者文檔文件。大多數常見文件類型都支持,包括.mp3.wav.mp4.mov.htm 和 .pdf等(完整列表請看 packager defaults)。

你也能夠建立本身的配置文件來支持其餘類型的文件。

須要注意的是視頻必須指定尺寸而不能使用flex樣式,由於咱們目前還不能從非圖片資源中獲取到尺寸信息。對於直接連接到 Xcode 或者 Android 資源文件夾的視頻,則不會有這個限制。

 

使用混合 App 的圖片資源

若是你在編寫一個混合 App(一部分 UI 使用 React Native,而另外一部分使用平臺原生代碼),也可使用已經打包到 App 中的圖片資源(以拖拽的方式放置在 Xcode 的 asset 類目中,或是放置在 Android 的 drawable 目錄裏)。注意此時只使用文件名,不帶路徑也不帶後綴你須要本身確保圖片在應用中確實存在,並且還須要指定尺寸

<Image source={{uri: 'app_icon'}} style={{width: 40, height: 40}} />

 

網絡圖片

不少要在 App 中顯示的圖片並不能在編譯的時候得到,又或者有時候須要動態載入來減小打包後的二進制文件的大小。這些時候,與靜態資源不一樣的是,你須要手動指定圖片的尺寸
<Image source={{
uri: 'https://facebook.github.io/react/logo-og.png'}} style={{width: 400, height: 400}} />

 

iOS 會爲同一張圖片在相冊中保存多個不一樣尺寸的副本。對於一處 200x200 大小的縮略圖,顯然不該該選擇最高質量的 3264x2448 大小的圖片。若是剛好有匹配的尺寸,那麼 React Native 會自動爲你選好。若是沒有,則會選擇最接近的尺寸進行縮放,但也至少縮放到比所需尺寸大出 50%,以使圖片看起來仍然足夠清晰。這一切過程都是自動完成的,因此你不用操心本身去完成這些繁瑣且易錯的代碼。

 

爲何不在全部狀況下都自動指定尺寸呢?

在瀏覽器中,若是你不給圖片指定尺寸,那麼瀏覽器會首先渲染一個 0x0 大小的元素佔位,而後下載圖片,在下載完成後再基於正確的尺寸來渲染圖片。這樣作的最大問題是 UI 會在圖片加載的過程當中上下跳動,使得用戶體驗很是差。

在React Native中咱們有意避免了這一行爲。如此一來開發者就須要作更多工做來提早知曉遠程圖片的尺寸(或寬高比),但咱們相信這樣能夠帶來更好的用戶體驗。然而,讀取本地靜態圖片(使用require('./my-icon.png')語法)則無需指定尺寸,由於它們的尺寸在加載時就能夠馬上知道。

好比這樣一個引用require('./my-icon.png')的實際輸出結果多是:

{"__packager_asset":true,"uri":"my-icon.png","width":591,"height":573}

資源屬性source是一個對象

在 React Native 中,另外一個值得一提的變更是咱們把src屬性改成了source屬性,並且並不接受字符串,正確的值是一個帶有uri屬性的對象。

<Image source={{uri: 'something.jpg'}} />

深層次的考慮是,這樣可使咱們在對象中添加一些元數據(metadata)。假設你在使用require('./my-icon.png'),那麼咱們就會在其中添加真實文件路徑以及尺寸等信息(這只是舉個例子,將來的版本中 require 的具體行爲可能會變化)。此外這也是考慮了將來的擴展性,好比咱們可能會加入精靈圖(sprites)的支持:在輸出{uri: ...}的基礎上,咱們能夠進一步輸出裁切信息{uri: ..., crop: {left: 10, top: 50, width: 20, height: 40}},這樣理論上就能夠在現有的代碼中無縫支持精靈圖的切分。

對於開發者來講,則能夠在其中標註一些有用的屬性,例如圖片的尺寸,這樣可使圖片本身去計算將要顯示的尺寸(而沒必要在樣式中寫死)。請在這一數據結構中自由發揮,存儲你可能須要的任何圖片相關的信息。

 

背景圖片與嵌套寫法

開發者們常面對的一種需求就是相似 web 中的背景圖(background-image)。要實現這一用例,只需使用<ImageBackground>組件(其 props 與<Image>徹底相同),而後把須要背景圖的子組件嵌入其中便可。

你能夠閱讀其文檔而後思考你是否有更好更簡單的佈局方案。注意你必須指定寬高樣式。

return (
 
<ImageBackground source={...} style={{width: '100%', height: '100%'}}>
    <
Text>Inside</Text>
  </
ImageBackground>
);

在主線程外解碼圖片

圖片解碼有可能會須要超過一幀的時間。在 web 上這是頁面掉幀的一大因素,由於解碼是在主線程中完成的。然而在 React Native 中,圖片解碼則是在另外一線程中完成的。在實際開發中,通常對圖片還沒下載完成時的場景都作了處理(添加 loading 等),而圖片解碼時顯示的佔位符只佔用幾幀時間,並不須要你改動代碼去額外處理。

 

 

 

 

 

定時器

  • setTimeout, clearTimeout
  • setInterval, clearInterval
  • setImmediate, clearImmediate
  • requestAnimationFrame, cancelAnimationFrame

requestAnimationFrame(fn)setTimeout(fn, 0)不一樣,前者會在每幀刷新以後執行一次,然後者則會盡量快的執行(在 iPhone5S 上有可能每秒 1000 次以上)。

setImmediate則會在當前 JavaScript 執行塊結束的時候執行,就在將要發送批量響應數據到原生以前。注意若是你在setImmediate的回調函數中又執行了setImmediate,它會緊接着馬上執行,而不會在調用以前等待原生代碼。Promise的實現就使用了setImmediate來執行異步調用。

InteractionManager

原生應用感受如此流暢的一個重要緣由就是在互動和動畫的過程當中避免繁重的操做。在 React Native 裏,咱們目前受到限制,由於咱們只有一個 JavaScript 執行線程。不過你能夠用InteractionManager來確保在執行繁重工做以前全部的交互和動畫都已經處理完畢。

應用能夠經過如下代碼來安排一個任務,使其在交互結束以後執行:

InteractionManager.runAfterInteractions(() => {
 
// ...須要長時間同步執行的任務...
});

requestAnimationFrame(): 用來執行在一段時間內控制視圖動畫的代碼

setImmediate/setTimeout/setInterval(): 在稍後執行代碼。注意這有可能會延遲當前正在進行的動畫。

runAfterInteractions(): 在稍後執行代碼,不會延遲當前進行的動畫。

觸摸處理系統會把一個或多個進行中的觸摸操做認定爲'交互',而且會將runAfterInteractions()的回調函數延遲執行,直到全部的觸摸操做都結束或取消了。

InteractionManager 還容許應用註冊動畫,在動畫開始時建立一個交互「句柄」,而後在結束的時候清除它。

var handle = InteractionManager.createInteractionHandle();
// 執行動畫... (`runAfterInteractions`中的任務如今開始排隊等候)
// 在動畫完成以後
InteractionManager.clearInteractionHandle(handle);
// 在全部句柄都清除以後,如今開始依序執行隊列中的任務

務必在卸載組件前清除定時器!

咱們發現不少 React Native 應用發生致命錯誤(閃退)是與計時器有關。具體來講,是在某個組件被卸載(unmount)以後,計時器卻仍然在運行。要解決這個問題,只需銘記在unmount組件時清除(clearTimeout/clearInterval)全部用到的定時器便可:

import React, { Component } from "react";

export default class Hello extends Component {
  componentDidMount() {
   
this.timer = setTimeout(() => {
     
console.log("把一個定時器的引用掛在this上");
    },
500);
  }
  componentWillUnmount() {

    // 若是存在this.timer,則使用clearTimeout清空。
   
// 若是你使用多個timer,那麼用多個變量,或者用個數組來保存引用,而後逐個clear
   
this.timer && clearTimeout(this.timer);
  }
}

 

 

 

 

調試

開啓調試的快捷鍵

iOS -> Connect Hardware Keyboard

 

訪問 App 內的開發菜單

你能夠經過搖晃設備或是選擇 iOS 模擬器的"Hardware"菜單中的"Shake Gesture"選項來打開開發菜單。

 iOS -> Command⌘ + D    Android -> Command⌘ + M

在發佈(production)版本中開發者菜單將沒法使用

 

刷新 JavaScript

iOS -> Command⌘ + R ,Android -> RR 

自動刷新

Enable Live Reload  +   Enable Hot Reloading

紅屏錯誤   console.error()

黃屏警告 console.warn()

 

Chrome 開發者工具

開啓 Debug JS Remotely -> http://localhost:8081/debugger-ui

在 Chrome 的菜單中選擇Tools → Developer Tools能夠打開開發者工具,也能夠經過鍵盤快捷鍵來打開(Mac 上是Command + Option + I,Windows 上是Ctrl + Shift + I或是 F12)。打開有異常時暫停(Pause On Caught Exceptions)選項,可以得到更好的開發體驗。

注意:使用 Chrome 調試目前沒法觀測到 React Native 中的網絡請求,你可使用功能更強大的第三方的react-native-debugger來進行觀測。

 

React Developer Tools

安裝npm install -g react-devtools

啓動react-devtools

性能監測:開發者菜單 -> "Pref Monitor"懸浮層中會顯示應用的當前幀數

 

訪問控制檯日誌

react-native log-ios
react-native log-android

 

真機調試

對於 iOS 真機來講,須要打開 RCTWebSocketExecutor.m文件,而後將其中的"localhost"改成你的電腦的 IP 地址,最後啓用開發者菜單中的"Debug JS Remotely"選項。

對於 Android 5.0+設備(包括模擬器)來講,將設備經過 USB 鏈接到電腦上後,可使用adb命令行工具來設定從設備到電腦的端口轉發:adb reverse tcp:8081 tcp:8081

 

 

 

性能

關於「幀」你所須要知道的

iOS 設備提供了每秒 60 的幀率,這就留給了開發者和 UI 系統大約 16.67ms 來完成生成一張靜態圖片(幀)所須要的全部工做。若是在這分派的 16.67ms 以內沒有可以完成這些工做,就會引起‘丟幀’的後果,使界面表現的不夠流暢。

開發菜單 ->Show FPS Monitor. 你會注意到有兩個不一樣的幀率.

JS 幀率(JavaScript 線程)

對大多數 React Native 應用來講,業務邏輯是運行在 JavaScript 線程上的。這是 React 應用所在的線程,也是發生 API 調用,以及處理觸摸事件等操做的線程。更新數據到原生支持的視圖是批量進行的,而且在事件循環每進行一次的時候被髮送到原生端,這一步一般會在一幀時間結束以前處理完(若是一切順利的話)。若是 JavaScript 線程有一幀沒有及時響應,就被認爲發生了一次丟幀。 例如,你在一個複雜應用的根組件上調用了this.setState,從而致使一次開銷很大的子組件樹的重繪,可想而知,這可能會花費 200ms 也就是整整 12 幀的丟失。此時,任何由 JavaScript 控制的動畫都會卡住。只要卡頓超過 100ms,用戶就會明顯的感受到。這種狀況常常發生在老的Navigator導航器的切換過程當中:當你 push 一個新的路由時,JavaScript 須要繪製新場景所需的全部組件,以發送正確的命令給原生端去建立視圖。因爲切換是由 JavaScript 線程所控制,所以常常會佔用若干幀的時間,引發一些卡頓。有的時候,組件會在componentDidMount函數中作一些額外的事情,這甚至可能會致使頁面切換過程當中多達一秒的卡頓。

另外一個例子是老的觸摸事件的響應:若是你正在 JavaScript 線程處理一個跨越多個幀的工做,你可能會注意到TouchableOpacity的響應被延遲了。這是由於 JavaScript 線程太忙了,不可以處理主線程發送過來的原始觸摸事件,結果TouchableOpacity就不能及時響應這些事件並命令主線程的頁面去調整透明度了。

 

UI 幀率(主線程)

不少人會注意到,NavigatorIOS的性能要比老的純 JS 實現的Navigator好的多。緣由就是它的切換動畫是徹底在主線程上執行的,所以不會被 JavaScript 線程上的掉幀所影響。

一樣,當 JavaScript 線程卡住的時候,你仍然能夠歡快的上下滾動ScrollView,由於ScrollView運行在主線程之上(儘管滾動事件會被分發到 JS 線程,可是接收這些事件對於滾動這個動做來講並沒必要要)。

 

性能問題的常見緣由

開發模式 (dev=true)

JavaScript 線程的性能在開發模式下是很糟糕的。這是不可避免的,由於有許多工做須要在運行的時候去作,譬如使你得到良好的警告和錯誤信息,又好比驗證屬性類型(propTypes)以及產生各類其餘的警告。請務必注意在release 模式下去測試性能。

 

console.log 語句

在運行打好了離線包的應用時,控制檯打印語句可能會極大地拖累 JavaScript 線程。注意有些第三方調試庫也可能包含控制檯打印語句,好比redux-logger,因此在發佈應用前請務必仔細檢查,確保所有移除。

這裏有個小技巧能夠在發佈時屏蔽掉全部的console.*調用。React Native 中有一個全局變量__DEV__用於指示當前運行環境是不是開發環境。咱們能夠據此在正式環境中替換掉系統原先的 console 實現。

if (!__DEV__) {
  global.console = {
   
info: () => {},
   
log: () => {},
   
warn: () => {},
   
debug: () => {},
   
error: () => {}
  };
}

還有個babel 插件能夠幫你移除全部的console.*調用。首先須要使用yarn add --dev babel-plugin-transform-remove-console來安裝,而後在項目根目錄下編輯(或者是新建)一個名爲·.babelrc`的文件,在其中加入:

{
 
"env": {
   
"production": {
     
"plugins": ["transform-remove-console"]
    }
  }
}

這樣在打包發佈時,全部的控制檯語句就會被自動移除,而在調試時它們仍然會被正常調用。

 

ListView 首次渲染緩慢或者因爲列表很大致使滑動很慢

用新的FlatList或者SectionList組件替代。除了簡化了API,這些新的列表組件在性能方面都有了極大的提高, 其中最主要的一個是不管列表有多少行,它的內存使用都是常數級的。

若是你的FlatList渲染得很慢, 請確保你使用了getItemLayout,它經過跳過對items的處理來優化你的渲染速度。

 

在重繪一個幾乎沒有什麼變化的頁面時,JS 幀率嚴重下降

你能夠實現shouldComponentUpdate函數來指明在什麼樣的確切條件下,你但願這個組件獲得重繪。若是你編寫的是純粹的組件(界面徹底由 props 和 state 所決定),你能夠利用PureComponent來爲你作這個工做。再強調一次,不可變的數據結構(immutable,即對於引用類型數據,不修改原值,而是複製後修改並返回新值)在提速方面很是有用 —— 當你不得不對一個長列表對象作一個深度的比較,它會使重繪你的整個組件更加快速,並且代碼量更少。

 

在屏幕上移動視圖(滾動,切換,旋轉)時,UI 線程掉幀

當具備透明背景的文本位於一張圖片上時,或者在每幀重繪視圖時須要用到透明合成的任何其餘狀況下,這種現象尤其明顯。設置shouldRasterizeIOS或者renderToHardwareTextureAndroid屬性能夠顯著改善這一現象。 注意不要過分使用該特性,不然你的內存使用量將會飛漲。在使用時,要評估你的性能和內存使用狀況。若是你沒有須要移動這個視圖的需求,請關閉這一屬性。

 

使用動畫改變圖片的尺寸時,UI 線程掉幀

在 iOS 上,每次調整 Image 組件的寬度或者高度,都須要從新裁剪和縮放原始圖片。這個操做開銷會很是大,尤爲是大的圖片。比起直接修改尺寸,更好的方案是使用transform: [{scale}]的樣式屬性來改變尺寸。好比當你點擊一個圖片,要將它放大到全屏的時候,就可使用這個屬性。

 

Touchable 系列組件不能很好的響應

有些時候,若是咱們有一項操做與點擊事件所帶來的透明度改變或者高亮效果發生在同一幀中,那麼有可能在onPress函數結束以前咱們都看不到這些效果。好比在onPress執行了一個setState的操做,這個操做須要大量計算工做而且致使了掉幀。解決方案是將onPress處理函數中的操做封裝requestAnimationFrame中:

handleOnPress() {
 
// 謹記在使用requestAnimationFrame、setTimeout以及setInterval時
 
// 要使用TimerMixin(其做用是在組件unmount時,清除全部定時器)
 
this.requestAnimationFrame(() => {
   
this.doExpensiveAction();
  });
}

分析

你能夠利用內置的分析器來同時獲取 JavaScript 線程和主線程中代碼執行狀況的詳細信息。

對於 iOS 來講,Instruments 是一個寶貴的工具庫,Android 的話可使用 systrace

But first, make sure that Development Mode is OFF! You should see __DEV__ === false, development-level warning are OFF, performance optimizations are ON in your application logs.

Another way to profile JavaScript is to use the Chrome profiler while debugging. This won't give you accurate results as the code is running in Chrome but will give you a general idea of where bottlenecks might be. Run the profiler under Chrome's Performance tab. A flame graph will appear under User Timing. To view more details in tabular format, click at the Bottom Up tab below and then select DedicatedWorker Thread at the top left menu.

 

使用 systrace 調試 Android UI 性能(Find your process)

  • UI Thread. This is where standard android measure/layout/draw happens. The thread name on the right will be your package name (in my case book.adsmanager) or UI Thread. The events that you see on this thread should look something like this and have to do with Choreographertraversals, and DispatchUI:

  • JS Thread. This is where JavaScript is executed. The thread name will be either mqt_js or <...> depending on how cooperative the kernel on your device is being. To identify it if it doesn't have a name, look for things like JSCallBridge.executeJSCall, etc:

  • Native Modules Thread. This is where native module calls (e.g. the UIManager) are executed. The thread name will be either mqt_native_modules or <...>. To identify it in the latter case, look for things like NativeCallcallJavaModuleMethod, and onBatchComplete:

  • Bonus: Render Thread. If you're using Android L (5.0) and up, you will also have a render thread in your application. This thread generates the actual OpenGL commands used to draw your UI. The thread name will be either RenderThread or <...>. To identify it in the latter case, look for things like DrawFrame and queueBuffer:

 

 

 

 

 

拆包(RAM bundles)和內聯引用

若是你有一個較爲龐大的應用程序,你可能要考慮使用RAM(Random Access Modules,隨機存取模塊)格式的 bundle 和內聯引用。這對於具備大量頁面的應用程序是很是有用的,這些頁面在應用程序的典型使用過程當中可能不會被打開。一般對於啓動後一段時間內不須要大量代碼的應用程序來講是很是有用的。例如應用程序包含複雜的配置文件屏幕或較少使用的功能,但大多數會話只涉及訪問應用程序的主屏幕更新。咱們能夠經過使用RAM格式來優化bundle的加載,而且內聯引用這些功能和頁面(當它們被實際使用時)。

 

加載 JavaScript

在 react-native 執行 JS 代碼以前,必須將代碼加載到內存中並進行解析。若是你加載了一個 50MB 的 bundle,那麼全部的 50mb 都必須被加載和解析才能被執行。RAM 格式的 bundle 則對此進行了優化,即啓動時只加載 50MB 中實際須要的部分,以後再逐漸按需加載更多的包。

內聯引用

內聯引用(require 代替 import)能夠延遲模塊或文件的加載懶加載機制,直到實際須要該文件。

 

啓用 RAM 格式

在 iOS 上使用 RAM 格式將建立一個簡單的索引文件,React Native 將根據此文件一次加載一個模塊。在 Android 上,默認狀況下它會爲每一個模塊建立一組文件。你能夠像 iOS 同樣,強制 Android 只建立一個文件,但使用多個文件能夠提升性能,並下降內存佔用。

在 Xcode 中啓用 RAM 格式,須要編輯 build phase 裏的"Bundle React Native code and images"。在../node_modules/react-native/scripts/react-native-xcode.sh.sh中添加 export BUNDLE_COMMAND="ram-bundle":

export BUNDLE_COMMAND="ram-bundle"
export NODE_BINARY=node
../node_modules/react-native/scripts/react-native-xcode.sh.sh

在 Android 上啓用 RAM 格式,須要編輯 android/app/build.gradle 文件。在apply from: "../../node_modules/react-native/react.gradle"以前修改或添加project.ext.react

project.ext.react = [
  bundleCommand:
"ram-bundle",
]

若是在 Android 上,你想使用單個索引文件(如前所述),請在 Android 上使用如下行:

project.ext.react = [
  bundleCommand:
"ram-bundle",
  extraPackagerArgs: [
"--indexed-ram-bundle"]
]

配置預加載及內聯引用

如今咱們已經啓用了RAM格式,然而調用require會形成額外的開銷。由於當遇到還沒有加載的模塊時,require須要經過bridge來發送消息。這主要會影響到啓動速度,由於在應用程序加載初始模塊時可能觸發至關大量的請求調用。幸運的是,咱們能夠配置一部分模塊進行預加載。爲了作到這一點,你將須要實現某種形式的內聯引用。

添加 packager 配置文件

在項目中建立一個名爲 packager 的文件夾,並建立一個名爲 config.js 的文件。添加如下內容:

const config = {
  transformer: {
    getTransformOptions: () => {
      return {
        transform: { inlineRequires:
true },
      };
    },
  },
};

module.exports = config;

在 Xcode 的 Build phase 中添加export BUNDLE_CONFIG="packager/config.js"

export BUNDLE_COMMAND="ram-bundle"
export BUNDLE_CONFIG="packager/config.js"
export NODE_BINARY=node
../node_modules/react-native/scripts/react-native-xcode.sh.sh

編輯 android/app/build.gradle 文件,添加bundleConfig: "packager/config.js",

project.ext.react = [
  bundleCommand:
"ram-bundle",
  bundleConfig:
"packager/config.js"
]

最後,在 package.json 的「scripts」下修改「start」命令來啓用配置文件:

"start": "node node_modules/react-native/local-cli/cli.js start --config ../../../../packager/config.js",

此時用npm start啓動你的 packager 服務即會加載配置文件。請注意,若是你仍然經過 xcode 或是 react-native run-android 等方式自動啓動 packager 服務,則因爲沒有使用上面的參數,不會加載配置文件。

 

調試預加載的模塊

在您的根文件 (index.(ios|android).js) 中,您能夠在初始導入(initial imports)以後添加如下內容:

const modules = require.getModules();
const moduleIds = Object.keys(modules);
const loadedModuleNames = moduleIds
  .filter(
moduleId => modules[moduleId].isInitialized)
  .map(
moduleId => modules[moduleId].verboseName);
const waitingModuleNames = moduleIds
  .filter(
moduleId => !modules[moduleId].isInitialized)
  .map(
moduleId => modules[moduleId].verboseName);

// make sure that the modules you expect to be waiting are actually waiting
console.log(
 
'loaded:',
  loadedModuleNames.length,
 
'waiting:',
  waitingModuleNames.length
);

// grab this text blob, and put it in a file named packager/modulePaths.js
console.log(`module.exports = ${JSON.stringify(loadedModuleNames.sort())};`);

當你運行你的應用程序時,你能夠查看 console 控制檯,有多少模塊已經加載,有多少模塊在等待。你可能想查看 moduleNames,看看是否有任何意外。注意在首次 import 時調用的內聯引用。你可能須要檢查和重構,以確保只有你想要的模塊在啓動時加載。請注意,您能夠根據須要修改 Systrace 對象,以幫助調試有問題的引用。

require.Systrace.beginEvent = (message) => {
 
if(message.includes(problematicModule)) {
   
throw new Error();
  }
}

雖然每一個 App 各有不一樣,但只加載第一個頁面所需的模塊是有普適意義的。把 loadedModuleNames 的輸出放到 packager/modulePaths.js 文件中。

 

更新配置文件

Returning to packager/config.js we should update it to use our newly generated modulePaths.js file.

const modulePaths = require('./modulePaths');
const resolve = require('path').resolve;
const fs = require('fs');

// Update the following line if the root folder of your app is somewhere else.
const ROOT_FOLDER = resolve(__dirname, '..');

const config = {
 
transformer: {
   
getTransformOptions: () => {
     
const moduleMap = {};
      modulePaths.forEach(
path => {
       
if (fs.existsSync(path)) {
          moduleMap[resolve(path)] =
true;
        }
      });
     
return {
       
preloadedModules: moduleMap,
       
transform: { inlineRequires: { blacklist: moduleMap } },
      };
    },
  },
 
projectRoot: ROOT_FOLDER,
};

module.exports = config;

在啓用RAM格式以後,配置文件中的preloadedModules條目指示哪些模塊須要預加載。當 bundle 被加載時,這些模塊當即被加載,甚至在任何 requires 執行以前。blacklist 代表這些模塊不該該被要求內聯引用,由於它們是預加載的,因此使用內聯沒有性能優點。實際上每次解析內聯引用 JavaScript 都會花費額外的時間。

 

 

 

 

 

 

JavaScript 運行時環境

在使用 React Native 時,你的 JavaScript 代碼將會運行在兩個不一樣的環境上:

  • 大多數狀況下,React Native 使用的是JavaScriptCore,也就是 Safari 所使用的 JavaScript 引擎。可是在 iOS 上 JavaScriptCore 並無使用即時編譯技術(JIT),由於在 iOS 中應用無權擁有可寫可執行的內存頁(所以沒法動態生成代碼)。
  • 在使用 Chrome 調試時,全部的 JavaScript 代碼都運行在 Chrome 中,而且經過 WebSocket 與原生代碼通訊。此時的運行環境是V8 引擎

雖然兩個環境很是相似,但開發者仍是可能碰到一些不一致的地方。將來咱們極可能會嘗試一些其餘的 JS 引擎,因此請儘可能避免使用依賴於特定運行環境的代碼。

常見的不一致好比有:iOS 上有部分日期構造函數未實現;Android 上重複定義的 props 可能會致使報錯。

 

JavaScript 語法轉換器

語法轉換器可使編寫代碼的過程更加享受,由於開發者能夠藉助轉換器直接使用新的 JavaScirpt 語法標準,而無需等待 JS 解釋器的支持。

React Native 內置了Babel 轉換器。你能夠查看Babel 的文檔來了解有關它能夠轉換的語法的詳情。

這裏能夠看到目前 React Native 默認開啓的語法轉換特性

注:若想學習相關語法,譯者推薦阮一峯老師的《ECMAScript 6 入門》以及論壇的討論帖

 

ES5

保留關鍵字: promise.catch(function() { });

 

ES6

箭頭函數 Arrow functions<C onPress={() => this.setState({pressed: true})}

塊級做用域 Block scopinglet greeting = 'hi';

數組的擴展運算 Call spreadMath.max(...array);

類 Classesclass C extends React.Component { render() { return <View />; } }

常量 Constantsconst answer = 42;

解構 Destructuringvar {isActive, style} = this.props;

for...offor (var num of [1, 2, 3]) {}

模塊 Modulesimport React, { Component } from 'react';

動態屬性鍵 Computed Propertiesvar key = 'abc'; var obj = {[key]: 10};

對象方法的簡寫 Object Consise Method: var obj = { method() { return 10; } };

對象屬性的簡寫 Object Short Notationvar name = 'vjeux'; var obj = { name };

參數的擴展運算 Rest Paramsfunction(type, ...args) { }

字符串模板 Template Literalsvar who = 'world'; var str = `Hello ${who}`;

 

ES8

參數列表末尾容許放置逗號 Function Trailing Commafunction f(a, b, c,) { }

異步函數 Async Functionsasync function doStuffAsync() { const foo = await doOtherStuffAsync(); };

 

Stage 3

對象的擴展運算 Object Spreadvar extended = { ...obj, a: 10 };

其餘特性

JSX<View style={{color: 'red'}} />

Flowfunction foo(x: ?number): string {}

__DEV__ 用於判斷當前是否開發環境的全局變量

 

 

 

 

 

 

直接操做

有時候咱們須要直接改動組件並觸發局部的刷新,但不使用 state 或是 props。譬如在瀏覽器中使用 React 庫,有時候會須要直接修改一個 DOM 節點,而在手機 App 中操做 View 時也會碰到一樣的狀況。在 React Native 中,setNativeProps就是等價於直接操做 DOM 節點的方法。

何時使用 setNativeProps 呢?

在(不得不)頻繁刷新而又遇到了性能瓶頸的時候。

直接操做組件並非應該常用的工具。通常來講只是用來建立連續的動畫,同時避免渲染組件結構和同步太多視圖變化所帶來的大量開銷。setNativeProps是一個「簡單粗暴」的方法,它直接在底層(DOM、UIView 等)而不是 React 組件中記錄 state,這樣會使代碼邏輯難以理清。因此在使用這個方法以前,請儘可能先嚐試用setStateshouldComponentUpdate方法來解決問題。

 

 

 

 

 

 

顏色

Components in React Native are styled using JavaScript. Color properties usually match how CSS works on the web.

紅-綠-藍

React Native 支持 rgb() 和 rgba() 兩種十六進制與函數方法

  • '#f0f' (#rgb)
  • '#ff00ff' (#rrggbb)
  • '#ff00ff'
  • 'rgba(255, 255, 255, 1.0)'
  • '#f0ff' (#rgba)
  • '#ff00ff00' (#rrggbbaa)

色調-飽和度-亮度

也支持 hsl() 和 hsla() 函數方法:

  • 'hsl(360, 100%, 100%)'
  • 'hsla(360, 100%, 100%, 1.0)'

透明度

rgba(0,0,0,0) 的快捷方式是:'transparent'

你還可使用顏色名稱來做爲顏色值. React Native 遵循CSS3 規範

  • aliceblue (#f0f8ff)
  • antiquewhite (#faebd7)
  • aqua (#00ffff)
  • aquamarine (#7fffd4)
  • azure (#f0ffff)
  • beige (#f5f5dc)
  • bisque (#ffe4c4)
  • black (#000000)
  • blanchedalmond (#ffebcd)
  • blue (#0000ff)
  • blueviolet (#8a2be2)
  • brown (#a52a2a)
  • burlywood (#deb887)
  • cadetblue (#5f9ea0)
  • chartreuse (#7fff00)
  • chocolate (#d2691e)
  • coral (#ff7f50)
  • cornflowerblue (#6495ed)
  • cornsilk (#fff8dc)
  • crimson (#dc143c)
  • cyan (#00ffff)
  • darkblue (#00008b)
  • darkcyan (#008b8b)
  • darkgoldenrod (#b8860b)
  • darkgray (#a9a9a9)
  • darkgreen (#006400)
  • darkgrey (#a9a9a9)
  • darkkhaki (#bdb76b)
  • darkmagenta (#8b008b)
  • darkolivegreen (#556b2f)
  • darkorange (#ff8c00)
  • darkorchid (#9932cc)
  • darkred (#8b0000)
  • darksalmon (#e9967a)
  • darkseagreen (#8fbc8f)
  • darkslateblue (#483d8b)
  • darkslategrey (#2f4f4f)
  • darkturquoise (#00ced1)
  • darkviolet (#9400d3)
  • deeppink (#ff1493)
  • deepskyblue (#00bfff)
  • dimgray (#696969)
  • dimgrey (#696969)
  • dodgerblue (#1e90ff)
  • firebrick (#b22222)
  • floralwhite (#fffaf0)
  • forestgreen (#228b22)
  • fuchsia (#ff00ff)
  • gainsboro (#dcdcdc)
  • ghostwhite (#f8f8ff)
  • gold (#ffd700)
  • goldenrod (#daa520)
  • gray (#808080)
  • green (#008000)
  • greenyellow (#adff2f)
  • grey (#808080)
  • honeydew (#f0fff0)
  • hotpink (#ff69b4)
  • indianred (#cd5c5c)
  • indigo (#4b0082)
  • ivory (#fffff0)
  • khaki (#f0e68c)
  • lavender (#e6e6fa)
  • lavenderblush (#fff0f5)
  • lawngreen (#7cfc00)
  • lemonchiffon (#fffacd)
  • lightblue (#add8e6)
  • lightcoral (#f08080)
  • lightcyan (#e0ffff)
  • lightgoldenrodyellow (#fafad2)
  • lightgray (#d3d3d3)
  • lightgreen (#90ee90)
  • lightgrey (#d3d3d3)
  • lightpink (#ffb6c1)
  • lightsalmon (#ffa07a)
  • lightseagreen (#20b2aa)
  • lightskyblue (#87cefa)
  • lightslategrey (#778899)
  • lightsteelblue (#b0c4de)
  • lightyellow (#ffffe0)
  • lime (#00ff00)
  • limegreen (#32cd32)
  • linen (#faf0e6)
  • magenta (#ff00ff)
  • maroon (#800000)
  • mediumaquamarine (#66cdaa)
  • mediumblue (#0000cd)
  • mediumorchid (#ba55d3)
  • mediumpurple (#9370db)
  • mediumseagreen (#3cb371)
  • mediumslateblue (#7b68ee)
  • mediumspringgreen (#00fa9a)
  • mediumturquoise (#48d1cc)
  • mediumvioletred (#c71585)
  • midnightblue (#191970)
  • mintcream (#f5fffa)
  • mistyrose (#ffe4e1)
  • moccasin (#ffe4b5)
  • navajowhite (#ffdead)
  • navy (#000080)
  • oldlace (#fdf5e6)
  • olive (#808000)
  • olivedrab (#6b8e23)
  • orange (#ffa500)
  • orangered (#ff4500)
  • orchid (#da70d6)
  • palegoldenrod (#eee8aa)
  • palegreen (#98fb98)
  • paleturquoise (#afeeee)
  • palevioletred (#db7093)
  • papayawhip (#ffefd5)
  • peachpuff (#ffdab9)
  • peru (#cd853f)
  • pink (#ffc0cb)
  • plum (#dda0dd)
  • powderblue (#b0e0e6)
  • purple (#800080)
  • rebeccapurple (#663399)
  • red (#ff0000)
  • rosybrown (#bc8f8f)
  • royalblue (#4169e1)
  • saddlebrown (#8b4513)
  • salmon (#fa8072)
  • sandybrown (#f4a460)
  • seagreen (#2e8b57)
  • seashell (#fff5ee)
  • sienna (#a0522d)
  • silver (#c0c0c0)
  • skyblue (#87ceeb)
  • slateblue (#6a5acd)
  • slategray (#708090)
  • snow (#fffafa)
  • springgreen (#00ff7f)
  • steelblue (#4682b4)
  • tan (#d2b48c)
  • teal (#008080)
  • thistle (#d8bfd8)
  • tomato (#ff6347)
  • turquoise (#40e0d0)
  • violet (#ee82ee)
  • wheat (#f5deb3)
  • white (#ffffff)
  • whitesmoke (#f5f5f5)
  • yellow (#ffff00)
  • yellowgreen (#9acd32)

 

 

 

 

集成到現有原生應用

相關文章
相關標籤/搜索