React-Native利用React Navigation实现页面跳转——很好的RN入门DEMO

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yingzizizizizizzz/article/details/82465722

功能:

1、简单的查看电影demo

2、点击按钮跳转

3、点击列表页中的某一条跳转到相应详情页

页面:

首页=>电影列表页=>详情页

总结:

1、练习了props,state,样式,长列表,网络,触摸事件,Flexbox布局(学习资料:http://flexboxfroggy.com/

2、练习了使用导航器跳转页面 https://reactnative.cn/docs/navigation/

注意项:

1、ScrollView和长列表组件的区别

ScrollView适合用来显示数量不多的滚动元素。放置在ScollView中的所有组件都会被渲染,哪怕有些组件因为内容太长被挤出了屏幕外。如果你需要显示较长的滚动列表,那么应该使用功能差不多但性能更好的FlatList组件。

长类表组件包括:FlatList组件和SectionList组件

FlatList组件用于显示一个垂直的滚动列表,其中的元素之间结构近似而仅数据不同。更适于长列表数据,且元素个数可以增删。和ScrollView不同的是,FlatList并不立即渲染所有元素,而是优先渲染屏幕上可见的元素。

如果要渲染的是一组需要分组的数据,也许还带有分组标签的,那么SectionList

2、网络方面

a、能使用的方法有:Fetch、基于 XMLHttpRequest 封装的第三方库,例如frisbee或是axios等、WebSocket 

b、不能使用的方法: jQuery,因为 jQuery 中还使用了很多浏览器中才有而 RN 中没有的东西、不是所有 web 中的 ajax 库都可以直接使用

c、使用Fetch的时候不要忘记catch

catch((error) =>{
        console.error(error);
      })

d、网络请求天然是一种异步操作(译注:同样的还有asyncstorage,请不要再问怎样把异步变成同步!无论在语法层面怎么折腾,它们的异步本质是无法变更的。异步的意思是你应该趁这个时间去做点别的事情,比如显示 loading,而不是让界面卡住傻等)。

问题:

  1. _this3.pressToApp is not a function

原因:在ES6中,如果在自定义的函数里使用了this关键字,则需要对其进行“绑定”操作,否则this的指向不对。(还有一些其他做法,如使用箭头函数等)

解决:this指向不对,renderMovie函数中的this指向不对,所以找不到this.pressToApp,在constructor中加上this.renderMovie =this.renderMovie.bind(this);

2.navigation一直不存在 (https://reactnavigation.org/docs/en/navigating.html RN导航器的入门教程)

原因:没有在上一个页面中把navigation作为属性传过来

<Button
          onPress={() => navigate('Listfile')}
          title="Chat with Lucy"
          navigation = {navigate}
        />

实现:

注意:因为用的教程(https://reactnative.cn/docs/navigation/)中的获取电影的链接,所以没有根据电影id来获得数据的链接,所以,我直接在详情页中获取电影列表的第二条作为详情数据。

列表页到详情页思路:根据列表页传到详情页的id来得到相应的这条数据

首页:app.js

import React from 'react';
import {
  AppRegistry,
  Text,
  View,
  Button,
  StyleSheet,
} from 'react-native';
import { StackNavigator } from 'react-navigation';
import ProfileScreen from './ProfileScreen'
import ListScreen from './ListScreen'

class FirstScreen extends React.Component {
  static navigationOptions = {
    title: 'Welcome',
  };
  render() {
    const { navigate } = this.props.navigation;
    return (
      <View style={styles.container}>
        <Text style={styles.headerText}>Hello, Chat App!</Text>
        <Button
          onPress={() => navigate('Listfile')}
          title="Chat with Lucy"
          navigation = {navigate}
        />
      </View>
    );
  }
}


const App = StackNavigator({
  Home: { screen: FirstScreen },
  Profile: { screen: ProfileScreen },
  Listfile:{screen:ListScreen},
});

const styles = StyleSheet.create({
  container:{
    display:'flex',
    alignItems:'center',
    justifyContent:'center',
  },
  headerText:{
    width:'70%',
    height:'70%',
    textAlign:'center',
    lineHeight:300,
  },
});

export default App;

列表页:ListScreen.js

import React, {Component} from 'react';
import {Image, FlatList, TouchableHighlight, StyleSheet, Text, View} from 'react-native';


import Profile from './ProfileScreen.js';

var REQUEST_URL =
"https://raw.githubusercontent.com/facebook/react-native/0.51-stable/docs/MoviesExample.json";

type Props = {};

export default class ListScreen extends Component {
  static navigationOptions = {
    title: '电影列表',
  };
  constructor(props) {
    super(props);   //这一句不能省略,照抄即可
    this.state = {
      data: [],
      loaded:false,
    };
    // 在ES6中,如果在自定义的函数里使用了this关键字,则需要对其进行“绑定”操作,否则this的指向不对
    // 像下面这行代码一样,在constructor中使用bind是其中一种做法(还有一些其他做法,如使用箭头函数等)
    this.fetchData = this.fetchData.bind(this);
    this.renderMovie =this.renderMovie.bind(this);
  }

  componentDidMount(){
    this.fetchData();
  }

  fetchData(){
    fetch(REQUEST_URL)
    .then((response)=>response.json())
    .then((responseData)=>{
      this.setState({
        data:this.state.data.concat(responseData.movies),
        loaded:true,
      });
    })
    .catch(error => {
      console.error(error);
    });
  }

  render() {
    if (!this.state.data) {
      return this.renderLoadingView();
    }
    return (
      <FlatList 
        data={this.state.data}
        renderItem={this.renderMovie}
        style={styles.list}
      />
      );
  }

  pressToDetail(rowID:number){
    this.props.navigation.navigate('Profile',{
        movieID:rowID,
    });
  }

  renderLoadingView(){
    return (
      <View style={styles.container}>
      <Text>
      正在加载电影数据。。。
      </Text>
      </View>
      );
  }

  renderMovie({item}){
    console.log({item});
    return (
      <TouchableHighlight onPress={()=>this.pressToDetail(item.id)}>
      <View style={styles.container}>
        <Image style={styles.thumbnail}  source={{uri:item.posters.thumbnail}} />
        <View style={styles.rightContainer}>
          <Text style={styles.title&&styles.test}>{item.title}</Text>
          <Text style={styles.year}>{item.year}</Text>
        </View>
      </View>
      </TouchableHighlight>
      );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
    flexDirection:'row',
    marginBottom:10,
    borderWidth:1,
    borderColor:'#ccc',
    borderStyle:'solid',
    padding:5,
    borderRadius:5,
    shadowColor:'#000',
    shadowOffset:{width:4,height:4},
    elevation: 4,
  },
  thumbnail:{
    width:53,
    height:81
  },
  rightContainer:{
    flex:1,
    paddingLeft:10,
  },
  title:{
    fontSize:20,
    marginBottom:10,
  },
  year:{
    color:'#ccc'
  },
  list:{
    paddingTop:20,
    backgroundColor:'#F5FCFF',
  },
  test:{
    color:'red'
  }
});

详情页:ProfileScreen.js

import React, {Component} from 'react';
import {StyleSheet,Image, Text, View} from 'react-native';

var REQUEST_URL =
"https://raw.githubusercontent.com/facebook/react-native/0.51-stable/docs/MoviesExample.json";
export default class ProfileScreen extends Component{
	constructor(props){
		super(props);
		this.state={
			id:this.props.movieID,
			detail:null,
		};
		this.fetchData=this.fetchData.bind(this);
	}

	static navigationOptions = {
		title:'详情'
	};

	componentDidMount(){
    	this.fetchData();
  	}

	fetchData(){
	    fetch(REQUEST_URL)
	    .then((response)=>response.json())
	    .then((responseData)=>{
	      this.setState({
	        detail:responseData.movies[1],
	      });
	    })
	    .catch(error => {
	      console.error(error);
	    });
  	}

	render(){
			if (!this.state.detail) {
				return this.renderLoading();
			}
			return this.renderDetail(this.state.detail);
		}

		renderLoading(){
    return (
      <View style={styles.container}>
      <Text>
      	正在加载电影数据。。。
      </Text>
      </View>
      )
  }

renderDetail(detail){
	console.log(detail);
	return (
			<View style={styles.container}>
				<View style={styles.grid,styles.header}>
					<Text style={styles.headerText}>{detail.title}</Text>
				</View>
				<View style={styles.grid,styles.middle}>
					<View style={styles.leftCell}>
						<Image style={styles.thumbnail}  source={{uri:detail.posters.thumbnail}} />
					</View>
					<View style={styles.rightCell}>
						<Text href="#">{detail.year}</Text>
					</View>
				</View>
				<View style={styles.grid,styles.footer}>
					<Text>Copyright MaJieing</Text>
				</View>
			</View>
		);
}
	}



const styles = StyleSheet.create({
	container:{
		flex: 1,
	    backgroundColor: '#F5FCFF',
	    justifyContent:'center',
	    // minHeight:400,
	},
	grid:{
		display:'flex',
	},
	header:{
		justifyContent:'center',
		alignItems:'center',
		width:'100%',
		height:'30%',
		backgroundColor:'#F5A79A'
	},
	headerText:{
		width:'70%',
	},
	leftCell:{
		backgroundColor:'#FADAC5',
		flex: 1,
		justifyContent:'center',
		alignItems:'center',
	},
	rightCell:{
		backgroundColor: '#F6B16E',
		flex: 1,
		justifyContent:'center',
		alignItems:'center',
	},
	
	middle:{
		height:'60%',
		flexDirection:'row',
	},
	footer:{
		backgroundColor:'#eeeeee',
		color:'#666666',
		fontSize:16,
		height:'10%',
		width:'100%',
		justifyContent:'center',
		alignItems:'center',
	},
	thumbnail:{
    	width:53,
    	height:81
  },
});

猜你喜欢

转载自blog.csdn.net/yingzizizizizizzz/article/details/82465722