寫在前面
這篇文章是“跟我一起學(xué)react-native”系列文章的第二篇。這系列文章會(huì)隨著這個(gè)新聞項(xiàng)目的進(jìn)行更新。想要跟我一起學(xué)習(xí)React Native的朋友可以關(guān)注我的微信公眾號(hào)iOS進(jìn)階指南,或者訂閱我的個(gè)人博客。
上一篇文章講了React Native的環(huán)境搭建過程,本篇文章將討論“水滴新聞”項(xiàng)目結(jié)構(gòu)的搭建。
最終效果

項(xiàng)目文件結(jié)構(gòu)
rn_shuidi
| - - - - - - - App.js
| - - - - - - - app.json
| - - - - - - - index.js
| - - - - - - - node_modules
| - - - - - - - shuidi
| - - - - - - - home
| - - - - - - - HomeScreen.js
| - - - - - - - NodeScreen.js
| - - - - - - - attention
| - - - - - - - me
| - - - - - - - android
| - - - - - - - ios
| - - - - - - - img
| - - - - - - - home_normal.png
| - - - - - - - home_selected.png
| - - - - - - - package.json
react-navigation
因?yàn)轫?xiàng)目中包含多個(gè)頁(yè)面,頁(yè)面之間切換要使用TabBar和Navigation,因此要使用react-navigation這個(gè)框架。
安裝react-navigation
cd rn_shuidi
npm install react-navigation
Navigation
下面以“主頁(yè)為例”創(chuàng)建navigation
App.js
import { createStackNavigator, createBottomTabNavigator } from 'react-navigation'
import HomeScreen from './shuidi/home/HomeScreen'
import NodeScreen from './shuidi/home/NodeScreen'
const HomeStack = createStackNavigator({
Home: { screen: HomeScreen },
Nodes: { screen: NodeScreen }
})
StackNavigation可類比為iOS中的UINavigation,是一種棧類型的導(dǎo)航結(jié)構(gòu)。
Home和Nodes分別是導(dǎo)航中的兩個(gè)頁(yè)面(控制器)。這里的名字會(huì)在執(zhí)行導(dǎo)航行為的時(shí)候使用到。
screen參數(shù)是要放在導(dǎo)航中的頁(yè)面。
HomeScreen.js
constructor(props) {
super(props)
this.state = { text: 'old' }
}
static navigationOptions = {
title: '主頁(yè)',
};
<Text>{this.state.text}</Text>
<Button
title="Go to NodeScreen"
onPress={() => {
this.props.navigation.navigate('Nodes', {
title: '測(cè)試節(jié)點(diǎn)', callback: ((data) => {
this.setState({ text: data })
})
})
}}
/>
navigationOptions是對(duì)導(dǎo)航的配置,這里設(shè)置了title。相當(dāng)于self.title="主頁(yè)"
點(diǎn)擊“Go to NodeScreen”這個(gè)Button后會(huì)跳轉(zhuǎn)到標(biāo)簽為“Nodes”的頁(yè)面,如果App.js的HomeStack中不包含“Nodes”標(biāo)簽則不會(huì)跳轉(zhuǎn)。
title和callback分別是傳遞到“Nodes”頁(yè)面的參數(shù)。其中callback是一個(gè)回調(diào),用來進(jìn)行反向傳值。當(dāng)“Nodes”頁(yè)面以“data”為參數(shù)回調(diào)callback之后,this.setState保存接受到的參數(shù),當(dāng)前頁(yè)面就會(huì)隨之改變。
NodeScreen.js
static navigationOptions = ({ navigation }) => {
return {
title: navigation.getParam('title', '節(jié)點(diǎn)'),
};
};
const callback = navigation.getParam('callback')
<Button
title="反向傳值測(cè)試"
onPress={() => {
this.props.navigation.goBack(),
callback('我是反向傳值')
}}
/>
navigation.getParam('title', '節(jié)點(diǎn)')獲取navigation中的title參數(shù)。
點(diǎn)擊“反向傳值測(cè)試”,回到上一級(jí)頁(yè)面,之后調(diào)用callback,把字符串“我是反向傳值”傳遞到上一級(jí)頁(yè)面。
TabBar
App.js
createBottomTabNavigator(
{
Home: HomeStack,
Attention: AttentionStack,
Me: MeStack
},
{
navigationOptions: ({ navigation }) => ({
tabBarLabel: ({focused, tintColor}) => {
const { routeName } = navigation.state
var title = ''
if (routeName === 'Home') {
title = '主頁(yè)'
} else if (routeName === 'Attention') {
title = '關(guān)注'
} else {
title = '我'
}
return <Text>{title}</Text>
},
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
var iconName = '';
if (routeName === 'Home') {
iconName = focused ? require('./img/home_selected.png') : require('./img/home_normal.png')
} else if (routeName === 'Attention') {
iconName = focused ? require('./img/attention_selected.png') : require('./img/attention_normal.png')
} else {
iconName = focused ? require('./img/me_selected.png') : require('./img/me_normal.png')
}
return <Image
source={iconName}
style={{ width: 26, height: 26 }}
/>
}
}),
tabBarOptions: {
activeTintColor: 'blue',
inactiveTintColor: 'black',
}
}
)
tabBarLabel和tabBarIcon分別是當(dāng)前標(biāo)簽頁(yè)顯示的標(biāo)題和圖片,其中圖片根據(jù)focused展示不同內(nèi)容。
在navigationbar的子頁(yè)面中隱藏tabbar
HomeStack.navigationOptions = ({ navigation }) => {
let tabBarVisible = true;
if (navigation.state.index > 0) {
tabBarVisible = false;
}
return {
tabBarVisible,
};
};
至此,項(xiàng)目結(jié)構(gòu)搭建完成了。這個(gè)過程中如遇到問題可以參考遇到的問題和解決方案??????
如果這篇文章能為你提供些許的幫助,我將不勝榮幸。如果你能慷慨的點(diǎn)個(gè)贊或者關(guān)注我,我將萬分感激。