![](https://box.kancloud.cn/ed8cce1cf49f9c77f23cb1243711d995_502x787.png) #### 创建组件 使用了后台数据请求 ~~~ //搜索组件 class SearchScreen extends React.Component{ constructor(props) { super(props); this.state = { text: '',data:[]}; this.requestData(); } requestData = () => { const url = apiUrl + "/search.php"; fetch(url).then(res => { return res.json(); }).then(res => { this.setState({ data: [...this.state.data, ...res], }); }).catch(err => { ToastAndroid.show('获取数据失败',ToastAndroid.SHORT); }); } render(){ return ( <View style={[styles.container,{backgroundColor:'#fff'}]}> <View style={{padding:10,flex:1,justifyContent:'center'}}> <View style={{flex:1}}> <TextInput style={{height: 34, borderColor: '#317EF3', marginTop:1,borderWidth: 1,paddingLeft:10}} onChangeText={(text) => this.setState({text})} underlineColorAndroid='transparent' /> </View> <View style={{flex:1}}> <Button onPress={()=>{ if(this.state.text == ''){ ToastAndroid.show("您好像没有输入任何关键字",ToastAndroid.SHORT); return false; } this.props.navigation.navigate('searchResult',{text:this.state.text}); }} title="搜一下" /> </View> </View> <View style={{flex:5}}> <FlatList data={this.state.data} keyExtractor={item => item.id} renderItem={({item}) => ( <TouchableOpacity onPress={() => this.props.navigation.navigate('dynamicDetail',{title:item.title})}> <View style={styles.item}> <View style={{flex:1}}> <Text style={styles.title}>{item.title}</Text> <Text style={styles.info}>xxxxxxxxxxxxxx</Text> <Text style={styles.time}>2017</Text> </View> </View> </TouchableOpacity> )} ItemSeparatorComponent={ ()=>( <View style={{backgroundColor:'#EBEBEB',height:5}}> </View> ) } ListHeaderComponent={ ()=>( <View style={{height:40,justifyContent:'center',alignItems:'center',backgroundColor:"#EBEBEB"}}> <Text>大家都在搜</Text> </View> ) } /> </View> </View> ); } } ~~~ 服务器端代码 ~~~ <?php header("Access-Control-Allow-Origin:*"); $page = 1; if (isset($_GET['page'])){ $page = intval($_GET['page']); } $data = array( array( 'id'=>1, 'title' => '中国人', 'info' => '一年前,国家主席习近平在世界经济论坛年会和联合国日内瓦总部发表两场历史性演讲,向世界描绘一幅构建人类命运共同体的壮美蓝图,产生了强烈反响。美国《外交政策》杂志说,这是“具有分水岭意义的时刻”。', 'time' => '2018-01-05 12:50:32' ), array( 'id'=>2, 'title' => '2', 'info' => '一年前,国家主席习近平在世界经济论坛年会和联合国日内瓦总部发表两场历史性演讲,向世界描绘一幅构建人类命运共同体的壮美蓝图,产生了强烈反响。美国《外交政策》杂志说,这是“具有分水岭意义的时刻”。', 'time' => '2018-01-05 12:50:32' ), array( 'id'=>3, 'title' => '3', 'info' => '一年前,国家主席习近平在世界经济论坛年会和联合国日内瓦总部发表两场历史性演讲,向世界描绘一幅构建人类命运共同体的壮美蓝图,产生了强烈反响。美国《外交政策》杂志说,这是“具有分水岭意义的时刻”。', 'time' => '2018-01-05 12:50:32' ), array( 'id'=>4, 'title' => '4', 'info' => '一年前,国家主席习近平在世界经济论坛年会和联合国日内瓦总部发表两场历史性演讲,向世界描绘一幅构建人类命运共同体的壮美蓝图,产生了强烈反响。美国《外交政策》杂志说,这是“具有分水岭意义的时刻”。', 'time' => '2018-01-05 12:50:32' ), array( 'id'=>5, 'title' => '5', 'info' => '一年前,国家主席习近平在世界经济论坛年会和联合国日内瓦总部发表两场历史性演讲,向世界描绘一幅构建人类命运共同体的壮美蓝图,产生了强烈反响。美国《外交政策》杂志说,这是“具有分水岭意义的时刻”。', 'time' => '2018-01-05 12:50:32' ), array( 'id'=>6, 'title' => '6', 'info' => '一年前,国家主席习近平在世界经济论坛年会和联合国日内瓦总部发表两场历史性演讲,向世界描绘一幅构建人类命运共同体的壮美蓝图,产生了强烈反响。美国《外交政策》杂志说,这是“具有分水岭意义的时刻”。', 'time' => '2018-01-05 12:50:32' ) , array( 'id'=>7, 'title' => '7', 'info' => '一年前,国家主席习近平在世界经济论坛年会和联合国日内瓦总部发表两场历史性演讲,向世界描绘一幅构建人类命运共同体的壮美蓝图,产生了强烈反响。美国《外交政策》杂志说,这是“具有分水岭意义的时刻”。', 'time' => '2018-01-05 12:50:32' ) , array( 'id'=>8, 'title' => '8', 'info' => '一年前,国家主席习近平在世界经济论坛年会和联合国日内瓦总部发表两场历史性演讲,向世界描绘一幅构建人类命运共同体的壮美蓝图,产生了强烈反响。美国《外交政策》杂志说,这是“具有分水岭意义的时刻”。', 'time' => '2018-01-05 12:50:32' ) , array( 'id'=>9, 'title' => '9', 'info' => '一年前,国家主席习近平在世界经济论坛年会和联合国日内瓦总部发表两场历史性演讲,向世界描绘一幅构建人类命运共同体的壮美蓝图,产生了强烈反响。美国《外交政策》杂志说,这是“具有分水岭意义的时刻”。', 'time' => '2018-01-05 12:50:32' ) ); $start = ($page - 1)*10; $data = array_slice($data, $start,10); header("content-type:text/json;charset=utf-8"); echo json_encode($data); ~~~ ![](https://box.kancloud.cn/0aaf1ac18c9d698f1bda173e67cb085b_476x780.png) #### 创建搜索结果组件 仅仅使用了一个webview ~~~ class SearchResultScreen extends React.Component{ constructor(props) { super(props); this.state = { url:'https://www.baidu.com/s?wd=' + this.props.navigation.state.params.text }; } render(){ return ( <View style={styles.container}> <WebView source={{uri:this.state.url}} userAgent={userAgent} /> </View> ); } } ~~~ ![](https://box.kancloud.cn/ef97941a87318a182a6b058ee1f73ab4_500x763.png) #### 添加组件至路由 ~~~ const MyApp = StackNavigator({ dynamicStack: { screen: TabScreen, navigationOptions: ({navigation}) => ({ headerStyle:styles.headerBar, headerTitleStyle:styles.headerTitle, headerTintColor:'#FFFFFF', headerRight:(<HeadScreen navigation={navigation}></HeadScreen>), }), }, dynamicDetail: { screen: DynamicDetailScreen, }, search:{ screen:SearchScreen, navigationOptions: ({navigation}) => ({ headerStyle:styles.headerBar, headerTitleStyle:styles.headerTitle, headerTintColor:'#FFFFFF', title:'搜一搜' }), }, searchResult:{ screen:SearchResultScreen, navigationOptions: ({navigation}) => ({ headerStyle:styles.headerBar, headerTitleStyle:styles.headerTitle, headerTintColor:'#FFFFFF', title:navigation.state.params.text+'-搜索结果' }), }, login:{ screen:LoginScreen, navigationOptions: ({navigation}) => ({ headerStyle:styles.headerBar, headerTitleStyle:styles.headerTitle, headerTintColor:'#FFFFFF', title:'用户登录' }), } }); ~~~ 在组件里使用 跳转 如果不能用,试试在调用组件时传 navigation 参数 ~~~ headerRight:(<HeadScreen navigation={navigation}></HeadScreen>) ~~~ #### 特别注意 **FlatList 组件里 render 用 () 来 包含组件代码** ~~~ renderItem={({item}) => ( <TouchableOpacity onPress={() => this.props.navigation.navigate('dynamicDetail',{title:item.title})}> <View style={styles.item}> <View style={{flex:1}}> <Text style={styles.title}>{item.title}</Text> <Text style={styles.info}>xxxxxxxxxxxxxx</Text> <Text style={styles.time}>2017</Text> </View> </View> </TouchableOpacity> )} ~~~ ~~~ <FlatList data={this.state.data} keyExtractor={item => item.id} renderItem={({item}) => ( <TouchableOpacity onPress={() => this.props.navigation.navigate('dynamicDetail',{title:item.title})}> <View style={styles.item}> <View style={{flex:1}}> <Text style={styles.title}>{item.title}</Text> <Text style={styles.info}>xxxxxxxxxxxxxx</Text> <Text style={styles.time}>2017</Text> </View> </View> </TouchableOpacity> )} ItemSeparatorComponent={ ()=>( <View style={{backgroundColor:'#EBEBEB',height:5}}> </View> ) } ListHeaderComponent={ ()=>( <View style={{height:40,justifyContent:'center',alignItems:'center',backgroundColor:"#EBEBEB"}}> <Text>大家都在搜</Text> </View> ) } /> ~~~ #### 完整代码 ~~~ import React from 'react'; import { ToastAndroid,FlatList, StyleSheet,View, Text,Button,Image,StatusBar,WebView,TouchableOpacity,TextInput} from 'react-native'; import { TabNavigator,StackNavigator} from 'react-navigation'; const apiUrl = 'http://192.168.10.119/app3'; const userAgent = 'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Mobile Safari/537.36'; //动态组件 class DynamicScreen extends React.Component { static navigationOptions = { title: '动态', tabBarIcon: ({ focused, tintColor }) => ( <Image source={require('./icon/ic_home_black_24dp.png')} style={{ width: 28, height: 28, tintColor: tintColor }} /> ), }; constructor(props) { super(props); this.state = { page: 1, refreshing: false, data: {}, totalPage:10 }; this.requestData(); }; handleRefresh = () => { this.setState({ page: 1, refreshing: true, data: [], }, () => { this.requestData(); }); } handleRefresh2 = () => { this.setState({ page: (this.state.page+1), refreshing: true }, () => { this.requestData(); }); } requestData = () => { if(this.state.page > this.state.totalPage){ ToastAndroid.show('没有数据啦 !', ToastAndroid.SHORT); this.setState({refreshing: false}); return false; } const url = apiUrl + "/data.php?page="+this.state.page; fetch(url).then(res => { return res.json(); }).then(res => { this.setState({ data: [...this.state.data, ...res], refreshing: false, totalPage:2 }); }).catch(err => { this.setState({refreshing: false}); ToastAndroid.show('获取数据失败',ToastAndroid.SHORT); }); } render() { return ( <View style={styles.container}> <FlatList keyExtractor={item => item.id} data={this.state.data} refreshing={this.state.refreshing} onRefresh={this.handleRefresh} onEndReached={this.handleRefresh2} onEndReachedThreshold={0.5} renderItem={({item}) => ( <TouchableOpacity onPress={() => this.props.navigation.navigate('dynamicDetail',{id:item.id,title:item.title})}> <View style={styles.item}> <View style={{flex:1}}> <Text style={styles.title}>{item.title}</Text> <Text style={styles.info}>{item.info}</Text> <Text style={styles.time}>{item.time}</Text> </View> </View> </TouchableOpacity> )} ItemSeparatorComponent={ ()=>( <View style={{backgroundColor:'#EBEBEB',height:5}}> </View> ) } ListEmptyComponent={ ()=>( <View style={{height:50,flex:1,alignItems:'center',justifyContent:'center',backgroundColor:'#fff'}}> <Text style={{color:'red'}}>暂无数据</Text> </View> ) } /> </View> ); } } //动态组件详情组件 class DynamicDetailScreen extends React.Component { static navigationOptions = ({ navigation }) => ({ title: navigation.state.params.title, headerStyle:styles.headerBar, headerTitleStyle:styles.headerTitle, headerTintColor:'#fff' }); render(){ return ( <View style={styles.container}> <WebView source={{uri:apiUrl + '/read.html'}} userAgent={userAgent} /> </View> ); } } //发现组件 class FindScreen extends React.Component { static navigationOptions = { title: '发现', tabBarIcon: ({ focused, tintColor }) => ( <Image source={require('./icon/ic_group_work_black_24dp.png')} style={{ width: 28, height: 28, tintColor: tintColor }} /> ), }; render() { return ( <View style={[styles.container,styles.findBody]}> <View style={styles.findView}> <Image source={require('./icon/ic_group_black_24dp.png')} style={styles.findViewIcon} /> <Text style={styles.findViewText}> 朋友圈 </Text> </View> <View style={styles.findView}> <Image source={require('./icon/ic_filter_center_focus_black_24dp.png')} style={styles.findViewIcon} /> <Text style={styles.findViewText}>扫一扫</Text> </View> <View style={styles.findView}> <Image source={require('./icon/ic_search_black_24dp.png')} style={styles.findViewIcon} /> <Text style={styles.findViewText}>搜一搜</Text> </View> <View style={styles.findView}> <Image source={require('./icon/ic_shopping_cart_black_24dp.png')} style={styles.findViewIcon} /> <Text style={styles.findViewText}>购物</Text> </View> <View style={[styles.findView,styles.findMT]}> <Image source={require('./icon/ic_games_black_24dp.png')} style={styles.findViewIcon} /> <Text style={styles.findViewText}>游戏</Text> </View> <View style={styles.findView}> <Image source={require('./icon/ic_code_black_24dp.png')} style={styles.findViewIcon} /> <Text style={styles.findViewText}>小程序</Text> </View> </View> ); } } //我的组件 class MyScreen extends React.Component { constructor(props){ super(props); } static navigationOptions = { title: '我的', tabBarIcon: ({ focused, tintColor }) => ( <Image source={require('./icon/ic_account_circle_black_24dp.png')} style={{ width: 28, height: 28, tintColor: tintColor }} /> ), }; render() { return ( <View style={styles.container}> <TouchableOpacity onPress={() => this.props.navigation.navigate('login')}> <View style={{height:160,alignItems:'center',justifyContent:'center',backgroundColor:'#374760',marginBottom:10}}> <Image source={require('./icon/my.png')} style={{ width: 96, height: 96,tintColor:'#F0F0F0' }} /> <Text style={{color:'#F0F0F0',marginTop:10,fontSize:16}}>立即登录</Text> </View> </TouchableOpacity> <View style={[styles.findView,styles.findMT]}> <Image source={require('./icon/ic_games_black_24dp.png')} style={[styles.findViewIcon,{tintColor:'red'}]} /> <Text style={styles.findViewText}>游戏</Text> </View> <View style={styles.findView}> <Image source={require('./icon/ic_code_black_24dp.png')} style={styles.findViewIcon} /> <Text style={styles.findViewText}>小程序</Text> </View> </View> ); } } //登录组件 class LoginScreen extends React.Component{ constructor(props) { super(props); }; render(){ return ( <View style={styles.container}> <Text>55555555555555555555</Text> </View> ); } } //定义tab组件 const TabScreen = TabNavigator({ dynamic: { screen: DynamicScreen }, find: { screen: FindScreen }, my:{ screen:MyScreen } },{ tabBarPosition: 'bottom',//选项卡位置 animationEnabled: true, tabBarOptions: { activeTintColor: '#72A7F7',//选中颜色 inactiveTintColor:'#919191',//未选中颜色 //设置选项卡的背景颜色 style: { backgroundColor: '#FFFFFF', borderTopWidth:1, borderTopColor:'#E3E3E3' }, //去掉安卓点击之后的小黄线 indicatorStyle: { height: 0 }, //是否显示icon图标 showIcon:true, showLabel:false, } }); //组件样式 const styles = StyleSheet.create({ container: { flex: 1, backgroundColor:'#EBEBEB' }, item: { flex:1, flexDirection:'row', padding:10, backgroundColor:'#fff', }, title:{ color:'#4D4F53', fontSize:18 }, info:{ color:'#4d4f53', fontSize:14, marginTop:5, fontWeight:'400' }, time:{ color:'gray', fontSize:12, marginTop:8 }, //动态组件图片 userphoto:{ width:40, height:40, tintColor:'#9E9E9E' }, //头部组件+ headAdd:{ width: 24, height: 24, tintColor: '#FFFFFF', marginRight:20, }, //发现组件样式 findView:{ backgroundColor:'#fff', marginTop:15, padding:10, alignItems:'center', flexDirection:'row', }, findViewText2:{ flex:8, }, findViewIcon:{ width:24, height:24, marginRight:15 }, findViewIcon2:{ flex:2, width:46, height:46, }, findViewText:{ fontSize:20, color:'#232323', fontWeight:'400' }, findBody:{ backgroundColor:'#EBEBEB' }, findMT:{ marginTop:0, borderTopWidth:1, borderTopColor:'#EBEBEB' }, headerBar:{ backgroundColor:'#264D7F', }, headerTitle:{ color:'#FFFFFF', fontSize:16 } }); class HeadScreen extends React.Component{ constructor(props) { super(props); } render(){ return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <TouchableOpacity onPress={() => { this.props.navigation.navigate('search'); }}> <Image source={require('./icon/ic_search_black_24dp.png')} style={styles.headAdd} /> </TouchableOpacity> </View> ); } } //搜索组件 class SearchScreen extends React.Component{ constructor(props) { super(props); this.state = { text: '',data:[]}; this.requestData(); } requestData = () => { const url = apiUrl + "/search.php"; fetch(url).then(res => { return res.json(); }).then(res => { this.setState({ data: [...this.state.data, ...res], }); }).catch(err => { ToastAndroid.show('获取数据失败',ToastAndroid.SHORT); }); } render(){ return ( <View style={[styles.container,{backgroundColor:'#fff'}]}> <View style={{padding:10,flex:1,justifyContent:'center'}}> <View style={{flex:1}}> <TextInput style={{height: 34, borderColor: '#317EF3', marginTop:1,borderWidth: 1,paddingLeft:10}} onChangeText={(text) => this.setState({text})} underlineColorAndroid='transparent' /> </View> <View style={{flex:1}}> <Button onPress={()=>{ if(this.state.text == ''){ ToastAndroid.show("您好像没有输入任何关键字",ToastAndroid.SHORT); return false; } this.props.navigation.navigate('searchResult',{text:this.state.text}); }} title="搜一下" /> </View> </View> <View style={{flex:5}}> <FlatList data={this.state.data} keyExtractor={item => item.id} renderItem={({item}) => ( <TouchableOpacity onPress={() => this.props.navigation.navigate('dynamicDetail',{title:item.title})}> <View style={styles.item}> <View style={{flex:1}}> <Text style={styles.title}>{item.title}</Text> <Text style={styles.info}>xxxxxxxxxxxxxx</Text> <Text style={styles.time}>2017</Text> </View> </View> </TouchableOpacity> )} ItemSeparatorComponent={ ()=>( <View style={{backgroundColor:'#EBEBEB',height:5}}> </View> ) } ListHeaderComponent={ ()=>( <View style={{height:40,justifyContent:'center',alignItems:'center',backgroundColor:"#EBEBEB"}}> <Text>大家都在搜</Text> </View> ) } /> </View> </View> ); } } //搜索结果组件 class SearchResultScreen extends React.Component{ constructor(props) { super(props); this.state = { url:'https://www.baidu.com/s?wd=' + this.props.navigation.state.params.text }; } render(){ return ( <View style={styles.container}> <WebView source={{uri:this.state.url}} userAgent={userAgent} /> </View> ); } } // myapp路由 const MyApp = StackNavigator({ dynamicStack: { screen: TabScreen, navigationOptions: ({navigation}) => ({ headerStyle:styles.headerBar, headerTitleStyle:styles.headerTitle, headerTintColor:'#FFFFFF', headerRight:(<HeadScreen navigation={navigation}></HeadScreen>), }), }, dynamicDetail: { screen: DynamicDetailScreen, }, search:{ screen:SearchScreen, navigationOptions: ({navigation}) => ({ headerStyle:styles.headerBar, headerTitleStyle:styles.headerTitle, headerTintColor:'#FFFFFF', title:'搜一搜' }), }, searchResult:{ screen:SearchResultScreen, navigationOptions: ({navigation}) => ({ headerStyle:styles.headerBar, headerTitleStyle:styles.headerTitle, headerTintColor:'#FFFFFF', title:navigation.state.params.text+'-搜索结果' }), }, login:{ screen:LoginScreen, navigationOptions: ({navigation}) => ({ headerStyle:styles.headerBar, headerTitleStyle:styles.headerTitle, headerTintColor:'#FFFFFF', title:'用户登录' }), } }); export default class App extends React.Component { render() { return <MyApp />; } } ~~~