先推荐一个学习的地址:https://ke.qq.com/webcourse/index.html#cid=203313&term_id=100240778&taid=1277855849978417&vid=s14139cbg2q
我看了一下,挺全的,我接下来应该会根据这个视频自己做一个App?
这个链接也是我在GitHub上面学习各位可爱的程序员的开源项目的时候看到的,接下来我们先来看这个博主的项目吧~
先放github地址:https://github.com/linchengzzz/rnTest
接下来我们来分析项目
项目运行出来的效果,应该是接口有些问题
接下来我们简单看看代码,发现亮点
//index.js
//这个是根入口文件
/**
* @format
* @lint-ignore-every XPLATJSCOPYRIGHT1
*/
import {AppRegistry} from 'react-native';
// import App from './App';
import App from './views/main.js';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
我们接下来看main.js
//views/main.js
import React, { Component } from 'react';
import { Icon } from 'react-native-elements';
//引入页面
import AboutPage from './book/about';
import BookPage from './book/index';
import MoviePage from './movie/index';
import BookDetailsPage from './book/detail';
import MovieDetailsPage from './common/webpage';
import { createStackNavigator, createBottomTabNavigator, createAppContainer } from "react-navigation";
//定义切换页面
const bottomTabNavigator = createBottomTabNavigator({
Book: BookPage,
Movie: MoviePage,
About: AboutPage
}, {
defaultNavigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Book') {
iconName = focused ? 'book' : 'book' ; //可以根据focused更换图标
} else if (routeName === 'Movie') {
iconName = 'movie';
}else{
iconName = 'stars';
}
return <Icon name={iconName} size={25} color={tintColor} />;
},
}),
//定义激活颜色,有的是直接改变图片
tabBarOptions: {
//根据是否激活,改变颜色
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
}
});
// 定义对应页面
const AppStack = createStackNavigator(
{
bottomTabNavigator: {
screen: bottomTabNavigator
},
Details: {
screen: BookDetailsPage,
// navigationOptions: {
// title: "图书详情"
// }
},
MovieDetails:{
screen: MovieDetailsPage,
}
}, {
initialRouteName: "bottomTabNavigator",
// 默认header bar样式配置
defaultNavigationOptions: {
headerTintColor: '#fff',
headerStyle: {
backgroundColor: '#2596f3',
height: 0 //影藏header
}
},
});
const AppContainer = createAppContainer(AppStack);
export default class App extends Component {
render() {
return (
<AppContainer />
);
}
}
分析对应页面
//views/book/about.js
import React, { Component } from 'react';
import { Text, View, ScrollView, StyleSheet } from 'react-native';
export default class About extends Component {
render(){
return (
<ScrollView>
<View style={styles.container}>
<Text style={styles.title}>
App Info
</Text>
<View style={styles.box}>
<Text style={styles.leftTitle}>版本</Text>
<Text style={styles.rightContent}>
v1.1_20190312
</Text>
</View>
<View style={styles.box}>
<Text style={styles.leftTitle}>课程地址</Text>
<Text style={styles.rightContent}>
https://ke.qq.com/webcourse/index.html#cid=203313&term_id=100240778&taid=1278010468801073&vid=e1414ek8gbc
</Text>
</View>
<View style={styles.box}>
<Text style={styles.leftTitle}>依赖组件</Text>
<Text style={styles.rightContent}>
react-native-elements、react-navigation、react-native-webview
</Text>
</View>
<View style={styles.box}>
<Text style={styles.leftTitle}>欠缺功能</Text>
<Text style={styles.rightContent}>
header:目前影藏了,设置了header高度为0
</Text>
</View>
</View>
</ScrollView>
)
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
padding: 10,
marginTop: 0,
lineHeight:30
},
title: {
fontWeight: "bold",
color: "#f33",
fontSize: 20
},
box:{
marginTop:20,
flex:1
},
leftTitle:{
fontSize:18,
color:"#333",
fontWeight:"800",
},
rightContent:{
fontSize:16,
color:"#999"
}
})
//封装的searchBar
//views/common/searchbar.js
import React, { Component } from 'react';
import { Text, View,TextInput, StyleSheet, TouchableOpacity } from 'react-native';
export default class SearchBar extends Component {
render() {
return (
<View style={styles.container}>
<View style={styles.inputContainer}>
<TextInput style={styles.input} {...this.props} />
</View>
<TouchableOpacity style={styles.btn} {...this.props}>
<Text style={styles.search}>搜索</Text>
</TouchableOpacity>
</View>
);
}
}
var styles = StyleSheet.create({
container:{
flexDirection:"row",
justifyContent:"flex-end",
alignItems:"center",
height:44,
marginTop:10
},
inputContainer:{
flex:1,
marginLeft:5
},
input:{
flex:1,
height:44,
borderWidth:1,
borderRadius:4,
borderColor:"#ccc",
paddingLeft:5
},
btn:{
55,
height:44,
marginLeft:5,
marginRight:5,
backgroundColor:"#23beff",
borderRadius:4,
justifyContent:"center",
alignItems:"center"
},
search:{
flex:1,
color:"#fff",
fontSize:15,
fontWeight:"bold",
textAlign:"center",
lineHeight:44
}
})
//views/book/index.js
import React, { Component } from 'react';
import { Text, View, ScrollView, Image, StyleSheet,TouchableOpacity } from 'react-native';
import SearchBar from '../common/searchbar';
import Util from '../common/util';
import Api from '../common/api';
export default class index extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
show: true,
keyword: 'react'
};
}
componentDidMount(){
// 初次请求数据
this.getData();
}
updateSearch = search => {
this.setState({ keyword: search });
}
//获取数据
searchText=()=>{
this.getData();
}
// 以下写法报错,不识别this
// searchText (){
// this.getData();
// }
// Util.loading 工具函数定义的loading
getData(){
// 显示loading
this.setState({
show: false
});
// 请求数据
var that = this;
var url = Api.book_search + '?count=20&q=' + this.state.keyword;
Util.getRequest(url, function (response) {
// 请求成功
if (!response.books || response.books.length == 0) {
return alert("未查询到数据");
}
// 显示loading,将请求结果赋值给data
that.setState({
show: true,
data: response.books
});
}, function (error) {
// 请求失败
alert(error);
});
}
render() {
return (
<ScrollView>
{/* 封装的搜索头部 */}
<SearchBar
placeholder="请输入关键词(书名、作者)..."
onChangeText={this.updateSearch}
onPress={this.searchText}
/>
{
// 请求数据时显示loading,请求成功显示列表
this.state.show ?
<View style={styles.container} >
{
this.state.data.map((item, i) => {
return (
<TouchableOpacity style={styles.list} key={i} onPress={() => this.props.navigation.push('Details', { 'bookID': item.id })}
activeOpacity={0.5}>
<Image source={{ uri: item.images.small }} style={styles.images} />
<View style={styles.rightbox}>
<Text style={styles.title}>{item.title}</Text>
<Text>价格:{item.price ? item.price : '暂无'}</Text>
<Text>作者:{
item.author.map(
function(vo){
return vo + ' ';
}
)
}</Text>
<Text>{item.publisher} {item.pubdate}</Text>
<Text>{item.pages ? item.pages : '未知'} 页</Text>
</View>
</TouchableOpacity>
);
})
}
</View>
: Util.loading
}
</ScrollView>
)
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: "center",
padding:10,
marginTop: 0
},
btn:{
100,
height:30
},
images: { 80, height: 100 },
title:{
fontWeight:"bold",
color:"#f33"
},
rightbox:{
flex:1,
marginLeft:10
},
list:{
flex: 1,
flexDirection: "row",
borderBottomColor: "#ccc",
borderBottomWidth: 1,
paddingTop:10,
paddingBottom:10
}
})
关于详情页
//views/book/detail.js
import React, { Component } from 'react';
import { Text, View, ScrollView, Image, StyleSheet } from 'react-native';
import { Icon,Header,Button } from 'react-native-elements';
import Util from '../common/util';
import Api from '../common/api';
import { TouchableHighlight, TouchableOpacity } from 'react-native-gesture-handler';
export default class BookDetail extends Component {
constructor(props) {
super(props);
this.state = {
bookID: '',
bookData: null
};
}
componentDidMount(){
// bookID = this.props.navigation.getParam('bookID', 26378583);
// this.setState({
// bookID: bookID
// })
this.getData();
}
getData(){
//这个是从后端获取的数据
// var url = Api.book_detail_id + this.state.bookID;
var url = Api.book_detail_id + this.props.navigation.getParam('bookID', 26378583);
var that = this;
Util.getRequest(url,function(data){
that.setState({
bookData: data
})
},function(error){
alert(error);
})
}
render(){
var bookData = this.state.bookData;
return (
<ScrollView>
{
bookData != null ?
<View>
{/* <Button
icon={{
name: "assignment-return",
size: 15,
color: "white"
}}
onPress={() => this.props.navigation.goBack()}
title="返回"
/> */}
<View style={styles.list}>
<Image source={{ uri: bookData.images.small }} style={styles.images} />
<View style={styles.rightbox}>
<Text style={styles.title}>{bookData.title}</Text>
<Text>价格:{bookData.price ? bookData.price : '暂无'}</Text>
<Text>作者:{
bookData.author.map(
function (vo) {
return vo + ' ';
}
)
}</Text>
<Text>{bookData.publisher} {bookData.pubdate}</Text>
<Text>{bookData.pages ? bookData.pages : '未知'} 页</Text>
</View>
</View>
<View style={{ marginTop: 10 }}>
<Text>图书简介</Text>
<Text>{bookData.summary}</Text>
</View>
<View style={{marginTop:10}}>
<Text>作者简介</Text>
<Text>{bookData.author_intro}</Text>
</View>
</View>
: Util.loading
}
</ScrollView>
)
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: "center",
padding: 10,
marginTop: 0
},
btn: {
100,
height: 30
},
images: { 80, height: 100 },
title: {
fontWeight: "bold",
color: "#f33"
},
rightbox: {
flex: 1,
marginLeft: 10
},
list: {
flex: 1,
flexDirection: "row",
borderBottomColor: "#ccc",
borderBottomWidth: 1,
paddingTop: 10,
paddingBottom: 10
}
})