接觸react-native
有一段時間了,感覺學習最大的難點就是 rn的國內資料不多,老外寫的文件看起來不舒服
其中在react-navigation
上面花了很長的時間,搞的心力憔悴,但是看國內的文章,很多都是2.x版本的,api不向下相容,各種報錯物件不存在,前期天天踩坑
後來看了很長時間的官方文件,才搞清楚react-navigation
的使用
所以在我感覺我現在已經踩過很多坑的情況下,我決定寫這篇文章,來幫助rn
開發者儘可能的跳過react-navigation
的一些坑
本人使用react-native的一些練習程式碼github
本文章基於 "react-navigation": "^3.0.9" 假如版本跨度比較大,本文可能就不適合了
另外,學習庫或者外掛最好的方式就官方閱讀文件(感覺有點打臉自己)
安裝
儘量不要看百度出來的文章,,例如**dn,比較陳舊,已經不是個當前版本,一定要看文件
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開發一些必備的外掛
工欲善其事,必先利其器,好的開發環境可以有效地加速開發速度,以及開發體驗感
使用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
資料夾內部進行導航器的管理
createStackNavigator
這個是最常見的一個導航器,大部分頁面都是通過他進行配置的,使用起來也很簡單
先看看官方說明
現在我們在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的配置請看官方文件的
createBottomTabNavigator
大部分的移動端專案都有底部導航欄,得益於單頁應用,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
,來自定義你的導航欄元件,這個比較複雜,我後期會寫一篇文章出來詳細說明
createMaterialBottomTabNavigator
這個給人一種開箱即用的感覺,至於專案當中具體選擇什麼,這個要看需求
文件明確指出,需要安裝以下庫
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都可以完成,發揮你的想象力?
關於底部導航器的配置很多,沒辦法通過一篇文章一一介紹,詳情請看官方文件
createMaterialTopTabNavigator
螢幕頂部的標籤欄, 可通過點選路線或水平滑動來切換不同的路由。 預設情況下, 轉換是動態的。 每個路由的螢幕元件將立即安裝。
可以看一下我之前模擬拼多多的頁面(當時是做技術驗證)
就這樣的效果
下面我們可以根據文件在我們的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配置全面屏 都得到了比較好的解決
RN相關文章
關於createDrawerNavigator
(抽屜元件) 和 createSwitchNavigator
(僅顯示一次頁面),放到後面再說~