接觸react-native
有一段時間了,感受學習最大的難點就是 rn的國內資料很少,老外寫的文檔看起來不舒服javascript
其中在react-navigation
上面花了很長的時間,搞的心力憔悴,可是看國內的文章,不少都是2.x版本的,api不向下兼容,各類報錯對象不存在,前期每天踩坑html
後來看了很長時間的官方文檔,才搞清楚react-navigation
的使用前端
因此在我感受我如今已經踩過不少坑的狀況下,我決定寫這篇文章,來幫助rn
開發者儘量的跳過react-navigation
的一些坑java
本人使用react-native的一些練習代碼githubreact
react-native官網android
本文章基於 "react-navigation": "^3.0.9" 假如版本跨度比較大,本文可能就不適合了git
另外,學習庫或者插件最好的方式就官方閱讀文檔(感受有點打臉本身)github
儘可能不要看百度出來的文章,,例如**dn,比較陳舊,已經不是個當前版本,必定要看文檔web
rn項目裏面,我推薦使用yarn, npm有時候會出現依賴不全的問題
在已經初始化完成,而且確保能夠運行的rn項目裏面,輸入一下命令
yarn add react-navigation
yarn add react-native-gesture-handler
react-native link react-native-gesture-handler
複製代碼
在已經搭建好的項目裏面,運行上面的命令,這都是必須的,詳情請看文檔React navigation安裝
安裝完成後啓動項目(啓動無報錯即意味着navigation安裝成功了)
沒有接觸過原生開發的web開發者看到這些很react風格的導航器名稱,必定很陌生,不要緊,後面圖示
rn上的導航器的編寫就是相似 前端的路由的編寫,經過rn的導航器來決定App的路由結構,以及個性化的頁面
createStackNavigator 最基本的頁面 自帶上方導航欄
爲你的應用程序提供一種在每一個新屏幕放置在堆棧頂部的屏幕之間轉換的方法。
createBottomTabNavigator
頁面底部的標籤欄,可以讓您在不一樣路由之間進行切換。 路由被懶加載 - 它們的屏幕組件只有在第一次獲取焦點時纔會被加載。
createMaterialBottomTabNavigator
功能上和 createBottomTabNavigator 同樣,這個更加個性化,可是咱們能夠基於createBottomTabNavigator
自定義任意底部導航欄
屏幕底部的材料設計主題標籤欄,可以讓您在不一樣路由之間切換。 路由被懶加載 - 它們的屏幕組件直到第一次獲取焦點時才被加載。
createMaterialTopTabNavigator
屏幕頂部左右滑動切換tab
屏幕頂部的材料設計主題標籤欄, 可經過點擊路線或水平滑動來切換不一樣的路由。 默認狀況下, 轉換是動態的。 每一個路由的屏幕組件將當即安裝。
createDrawerNavigator: 抽屜效果導航器,由側邊劃出;
createSwitchNavigator:
createSwitchNavigator 的用途是一次只顯示一個頁面。 默認狀況下,它不處理返回操做,並在你切換時將路由重置爲默認狀態。(特定場合纔會使用)
經常使用的導航器就這麼多,下面將一一介紹給你們
工欲善其事,必先利其器,好的開發環境能夠有效地加速開發速度,以及開發體驗感
使用vscode開發,推薦安裝Full React/React Native/React Router/Redux/GraphQL/ES7/Testing/PropTypes snippets
另外開發react推薦插件
React Native Snippet
React Native Tools
Reactjs code snippets
以上插件安裝完成後,就基本知足使用vscode進行react native的開發了 :wink:
安裝好的項目咱們稍微改造一下,
one.js
two.js
three.js
是頁面 隨便寫點什麼就好
navigation
文件夾內部進行導航器的管理
這個是最多見的一個導航器,大部分頁面都是經過他進行配置的,使用起來也很簡單
先看看官方說明
如今咱們在navigation
/index.js
進行路由的配置
import { createStackNavigator, createAppContainer } from 'react-navigation'
import One from '../pages/One'
import Two from '../pages/Two'
import Three from '../pages/Three'
const Stack = createStackNavigator({
One: {
screen: One
},
Two: {
screen: Two
},
Three: {
screen: Three
}
})
export default createAppContainer(Stack)
// createAppContainer是 react-navigation 的app容器,並將頂層的 navigator 連接到整個應用環境(後面再說)
複製代碼
如今咱們須要在根節點導出這個導航器配置,因此須要修改根目錄的App.js
import React, { Component } from 'react'
import Navigation from './app/navigation'
export default class App extends Component {
render() {
return <Navigation /> } } 複製代碼
這個咱們就導出導航器配置,接下來重啓項目
成功了!
可是目前還不能進行頁面以前的切換,react-navigation
提供了導航器以前的切換功能
關於切換路由 react-navigation 提供了不少api,下圖是最基礎的一部分
還記得前面建立容器的API createAppContainer嗎
他在props裏面提供了navigation對象,用於進行導航器切換
在One.js裏面添加切導航器的代碼One.js
import React, { Component } from 'react'
import { Text, View, Button } from 'react-native'
export default class One extends Component {
render() {
return (
<View> <Text> One </Text> <Button title="跳轉到Two頁面" onPress={() => { this.props.navigation.navigate('Two') }} /> </View> ) } } 複製代碼
原生的感受真的棒~
咱們不只能夠切換頁面,還能夠像原生同樣配置頁面,react-navigation
提供了大量的導航的自定義配置
例如
咱們能夠添加頁面標題,ios與android,導航欄會自適應
咱們能夠任意的選擇顯示或者不顯示導航欄
設置導航欄顏色 等等你能夠想到的個性化設置
更新naviigation
/index.js
import { createStackNavigator, createAppContainer } from 'react-navigation'
import One from '../pages/One'
import Two from '../pages/Two'
import Three from '../pages/Three'
const Stack = createStackNavigator({
One: {
screen: One,
navigationOptions: {
title: 'One'
}
},
Two: {
screen: Two,
navigationOptions: {
title: 'Two',
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}
},
Three: {
screen: Three,
navigationOptions: {
title: 'Three'
}
}
},{
})
export default createAppContainer(Stack)
複製代碼
更多的navigationOptions的配置請看官方文檔的
大部分的移動端項目都有底部導航欄,得益於單頁應用,webapp更多的出如今原生端那麼在react-native上,如何建立一個底部導航欄呢?
從web的角度理解 就是 經過底部導航欄進行組件的懶加載切換
讓咱們根據官方文檔建立一個導航欄試試
修改navigation
/index.js
import {
createStackNavigator,
createBottomTabNavigator,
createAppContainer
} from 'react-navigation'
import One from '../pages/One'
import Two from '../pages/Two'
import Three from '../pages/Three'
const BottomBar = createBottomTabNavigator(
{
One: {
screen: One,
navigationOptions: {
title: 'One'
}
},
Two: {
screen: Two,
navigationOptions: {
title: 'Two'
}
},
Three: {
screen: Three,
navigationOptions: {
title: 'Three'
}
}
},
{
initialRouteName: 'One' // 初始化頁面
}
)
const Stack = createStackNavigator({
BottomBar: {
screen: BottomBar,
navigationOptions: {
header: null
}
}
})
export default createAppContainer(Stack)
複製代碼
咱們引入了createBottomTabNavigator
在createBottomTabNavigator
裏面加了3個頁面,最後將導出的底部導航器對象再加入到createStackNavigator
中,做爲普通頁面的形式
基礎的底部導航器實現了~
在基礎API上面,咱們能夠作不少自定義的操做,自定義圖標自定義文字,等等,具體請看文檔
下面咱們給咱們的導航欄加一個圖標,讓他看起來更加美觀
在項目裏面添加幾個小icon(圖片用的是iconfont上面的)
網絡上9成的文章都說明了在rn項目裏面使用 react-native-vector-icons 這個圖標庫進行圖標的添加 我這裏使用不常見的方案,使用本地png圖片做爲底部icon,固然這個使用在具體項目裏面應該封裝起來,這樣類小程序的模式,我相信能夠很好的幫助理解,如下編碼方式僅供學習
修改navigation
/index.js
import React from 'react'
import { Image } from 'react-native'
import {
createStackNavigator,
createBottomTabNavigator,
createAppContainer
} from 'react-navigation'
import One from '../pages/One'
import Two from '../pages/Two'
import Three from '../pages/Three'
const BottomBar = createBottomTabNavigator(
{
One: {
screen: One,
navigationOptions: {
title: 'One',
tabBarIcon: ({ tintColor }) => {
let sourceImg
if (tintColor == '#1296db') {
sourceImg = require('../image/one-active.png')
} else {
sourceImg = require('../image/one.png')
}
return (
<Image
source={sourceImg}
style={{ width: 24, height: 24 }}
color={tintColor}
/>
)}
}
},
Two: {
screen: Two,
navigationOptions: {
title: 'Two',
tabBarIcon: ({ tintColor }) => {
console.log(tintColor);
let sourceImg
if (tintColor == '#1296db') {
sourceImg = require('../image/my-active.png')
} else {
sourceImg = require('../image/my.png')
}
return (
<Image
source={sourceImg}
style={{ width: 24, height: 24 }}
color={tintColor}
/>
)}
}
},
Three: {
screen: Three,
navigationOptions: {
title: 'Three',
tabBarIcon: ({ tintColor }) => {
let sourceImg
if (tintColor == '#1296db') {
sourceImg = require('../image/message-active.png')
} else {
sourceImg = require('../image/message.png')
}
return (
<Image
source={sourceImg}
style={{ width: 24, height: 24 }}
color={tintColor}
/>
)}
}
}
},
{
initialRouteName: 'One', // 初始化頁面
tabBarOptions: {
activeTintColor: '#1296db',
inactiveTintColor: 'black'
}
}
)
const Stack = createStackNavigator({
BottomBar: {
screen: BottomBar,
navigationOptions: {
header: null
}
}
})
export default createAppContainer(Stack)
複製代碼
reactnavigation的導航欄只能作這些嗎?固然不是,能夠經過指定tabBarComponent
,來自定義你的導航欄組件,這個比較複雜,我後期會寫一篇文章出來詳細說明
這個給人一種開箱即用的感受,至於項目當中具體選擇什麼,這個要看需求
文檔明確指出,須要安裝如下庫
yarn add react-navigation-material-bottom-tabs react-native-paper react-native-vector-icons
react-native link react-native-vector-icons
複製代碼
咱們來實現一下官方案例的效果
修改navigation
/index.js
import React from 'react'
import {
createStackNavigator,
createAppContainer
} from 'react-navigation'
import { createMaterialBottomTabNavigator } from 'react-navigation-material-bottom-tabs'
import Ionicons from 'react-native-vector-icons/Ionicons'
import One from '../pages/One'
import Two from '../pages/Two'
import Three from '../pages/Three'
const BottomMater = createMaterialBottomTabNavigator(
{
One: {
screen: One,
navigationOptions: {
tabBarColor: '#3472EE', // 頁面背景色
tabBarIcon: ({ tintColor }) => (
<Ionicons name="ios-home" color={tintColor} size={24} />
)
}
},
Two: {
screen: Two,
navigationOptions: {
tabBarColor: '#EC3E3E',
tabBarIcon: ({ tintColor }) => (
<Ionicons name="ios-options" color={tintColor} size={24} />
)
}
},
Three: {
screen: Three,
navigationOptions: {
tabBarColor: '#0EA748',
tabBarIcon: ({ tintColor }) => (
<Ionicons name="ios-chatbubbles" color={tintColor} size={24} />
)
}
}
},
{
initialRouteName: 'One',
activeColor: 'white',
inactiveColor: 'gray',
shifting: true
}
)
const Stack = createStackNavigator({
BottomMater: {
screen: BottomMater,
navigationOptions: {
header: null
}
}
})
export default createAppContainer(Stack)
複製代碼
這樣相似的效果,react-navitation均可以完成,發揮你的想象力🤣
關於底部導航器的配置不少,沒辦法經過一篇文章一一介紹,詳情請看官方文檔
屏幕頂部的標籤欄, 可經過點擊路線或水平滑動來切換不一樣的路由。 默認狀況下, 轉換是動態的。 每一個路由的屏幕組件將當即安裝。
能夠看一下我以前模擬拼多多的頁面(當時是作技術驗證)
就這樣的效果
下面咱們能夠根據文檔在咱們的demo項目裏面本身實現一下這樣的效果
新增兩個頁面 Four.js
Five.js
隨便寫點什麼就行
爲了更加合理設置邏輯,我將TopBar的全部導航器配置代碼放到一個文件當中
在navigation
文件夾內新建文件TopBar.js
import { createMaterialTopTabNavigator } from 'react-navigation'
import One from '../pages/One'
import Four from '../pages/Four'
import Five from '../pages/Five'
export default createMaterialTopTabNavigator(
{
One: {
screen: One, // 配置頁面
navigationOptions: {
tabBarLabel: 'One'
}
},
Four: {
screen: Four,
navigationOptions: {
tabBarLabel: 'Four'
}
},
Five: {
screen: Five,
navigationOptions: {
tabBarLabel: 'Five'
}
}
},
{
initialRouteName: 'One',
lazy: true,
tabBarOptions: {
scrollEnabled: true,
upperCaseLabel: false, // 是否大寫
activeTintColor: 'red', // 活動選項卡
inactiveTintColor: 'red', // "非活動" 選項卡
tabStyle: {
// 選項卡樣式
// width: 60,
// paddingTop: 35,
paddingBottom: 4
},
style: {
backgroundColor: 'white' // 頭部導航欄樣式
},
indicatorStyle: {
backgroundColor: 'red' // 指示器樣式
}
}
}
)
複製代碼
最後修改navigation
/index.js
,將咱們新建的頂部導航器導入
import React from 'react'
import { Image } from 'react-native'
import {
createStackNavigator,
createBottomTabNavigator,
createAppContainer
} from 'react-navigation'
import { createMaterialBottomTabNavigator } from 'react-navigation-material-bottom-tabs'
import Ionicons from 'react-native-vector-icons/Ionicons'
import TopBar from './TopBar'
import Two from '../pages/Two'
import Three from '../pages/Three'
const BottomMater = createMaterialBottomTabNavigator(
{
TopBar: {
screen: TopBar,
navigationOptions: {
tabBarColor: '#3472EE', // 頁面背景色
tabBarIcon: ({ tintColor }) => (
<Ionicons name="ios-home" color={tintColor} size={24} />
)
}
},
Two: {
screen: Two,
navigationOptions: {
tabBarColor: '#EC3E3E',
tabBarIcon: ({ tintColor }) => (
<Ionicons name="ios-options" color={tintColor} size={24} />
)
}
},
Three: {
screen: Three,
navigationOptions: {
tabBarColor: '#0EA748',
tabBarIcon: ({ tintColor }) => (
<Ionicons name="ios-chatbubbles" color={tintColor} size={24} />
)
}
}
},
{
initialRouteName: 'TopBar',
activeColor: 'white',
inactiveColor: 'gray',
shifting: true
}
)
const Stack = createStackNavigator({
BottomMater: {
screen: BottomMater,
navigationOptions: {
header: null
}
}
})
export default createAppContainer(Stack)
複製代碼
是否是很簡單,或者所,是否是學會了react-navigation的套路了 ~
到這裏多聯繫,多理解,基本能夠完成通常項目的搭建了,
你也能夠看看我寫過的其餘文章,或者一些react-native的倉庫代碼,
定位 消息推送 APP啓動屏 第三方集成 RN配置全面屏 都獲得了比較好的解決
關於createDrawerNavigator
(抽屜組件) 和 createSwitchNavigator
(僅顯示一次頁面),放到後面再說~