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,而不是让界面卡住傻等)。
原因:在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作为属性传过来
注意:因为用的教程(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 (
Hello, Chat App!
);
}
}
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 (
);
}
pressToDetail(rowID:number){
this.props.navigation.navigate('Profile',{
movieID:rowID,
});
}
renderLoadingView(){
return (
正在加载电影数据。。。
);
}
renderMovie({item}){
console.log({item});
return (
this.pressToDetail(item.id)}>
{item.title}
{item.year}
);
}
}
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 (
正在加载电影数据。。。
)
}
renderDetail(detail){
console.log(detail);
return (
{detail.title}
{detail.year}
Copyright MaJieing
);
}
}
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
},
});