其他的一些问题 记录下
加括号情况: 当函数需要立即执行的时候(需要立刻返回)
不加括号情况: 当事件需要延迟触发的时候. (比如点击事件的函数)
static propTypes = {
}
```
static defaultProps = {
}
propTypes 是用于传入类型的校验
defaultProps 是给props 设置默认的值
https://segmentfault.com/a/1190000007814801
http://blog.csdn.net/vispin/article/details/53002586
先来一张这次写的最终的效果
分析下布局,我的页面,首先顶部是一个导航栏 我的,这个导航栏可以复用之前写的NavigationBar.js,
但是之前的文字是写死的,右边的控件也是写死的,现在需要把文字和右边的控件作为属性传过去
因为顶部控件是通用的 把他抽取出来
我敲下面的代码的时候
遇到的问题.
1,render() 没有 写 return 直接写了一个View 我一直在找这个问题 巨痛苦
2,出现PropTypes is not defined . 原来PropTypes这个东西 需要引入,和Compoent一起引入
在这里记录下
动态传递控件 顶部控件
再分析下 顶部导航栏是由三部分组成 左边视图 中间标题 右边视图
,那么我在NavigationBar里面接收从其他页面传递过来的组件就可以实现
顶部控件是动态的了.
那么现在先改造NavigationBar
/** * Created by liuml on 2017/9/11. */
import React,{Component,PropTypes} from 'react';
import {
AppRegistry,StyleSheet,Text,View,StatusBar,Platform,Image,TouchableOpacity
} from 'react-native';
export default class NavigationBar extends Component {
static propTypes = {
//验证,不传element组件类型,会报错提示
rightButton: PropTypes.element,leftButton: PropTypes.element
}
render() {
return <View style={styles.container}>
<View style={styles.container}>
<StatusBar hidden={false} barStyle="light-content"/>
</View>
{/*顶部导航栏*/}
<View style={styles.navBar}>
<View style={styles.leftBtnStyle}>
{this.props.leftButton}
</View>
<View style={styles.titleWrapper}>
<Text style={styles.title}>{this.props.title}</Text>
</View>
<View style={styles.rightBar}>
{this.props.rightButton}
</View>
</View>
</View>
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#63B8FF',},statusBar: {
height: Platform.OS === 'ios' ? 20 : 0
},navBar: {
flexDirection: 'row',justifyContent: 'space-between',alignItems: 'center',titleWrapper: {
flexDirection: 'column',justifyContent: 'center',position: 'absolute',left: 40,right: 40,title: {
fontSize: 16,color: '#FFF'
},navBtn: {
width: 24,height: 24
},rightBar: {
flexDirection: 'row',paddingRight: 8
},leftBtnStyle: {
flexDirection: 'row',});
可以看到关键的几行代码
static propTypes = {
//验证,不传element组件类型,会报错提示
rightButton: PropTypes.element,leftButton: PropTypes.element
}
这是用于校验传入的左边的和右边的 是不是一个节点
{/*顶部导航栏*/}
<View style={styles.navBar}>
<View style={styles.leftBtnStyle}>
{this.props.leftButton}
</View>
<View style={styles.titleWrapper}>
<Text style={styles.title}>{this.props.title}</Text>
</View>
<View style={styles.rightBar}>
{this.props.rightButton}
</View>
</View>
这是给顶部导航栏设置左边中间和右边的控件 通过props传递
然后在PapularPage 里面创建标题栏 右边的控件
/**
* Created by liuml on 2017/9/11.
*/
import React,{Component} from 'react';
import {
AppRegistry,ListView,RefreshControl,TouchableOpacity
}from 'react-native';
import NavigationBar from "../compoent/NavigationBar.js"
import ScrollableTabView from "react-native-scrollable-tab-view"
import ProjectRow from "../compoent/ProjectRow"
export default class PapularPage extends Component {
// 构造
constructor(props) {
super(props);
// 初始状态
this.state = {
languages: ["Android","Ios","Java","React","JS"]
};
}
getRightBtn = () => {
return <View style={{flexDirection: 'row',alignItems: 'center'}}>
<TouchableOpacity activeOpacity={0.7}>
<Image source={require('../../res/images/ic_search_white_48pt.png')}
style={{width:24,height:24}}></Image>
</TouchableOpacity>
<TouchableOpacity activeOpacity={0.7}>
<Image source={require('../../res/images/ic_more_vert_white_48pt.png')}
style={{width:24,height:24}}></Image>
</TouchableOpacity>
</View>
}
render() {
return <View style={styles.container}>
<NavigationBar
rightButton={this.getRightBtn()}
title="热门"/>
<ScrollableTabView
tabBarBackgroundColor="#63B8FF"
tabBarActiveTextColor="#FFF"
tabBarInactiveTextColor="#F5FFFA"
tabBarUnderlineStyle={{backgroundColor: "#E7E7E7",height: 2}}>
{
this.state.languages.map((item,i) => { return <PopularTab key={`tab${i}`} tabLabel={item}/> }) } </ScrollableTabView> </View> } } class PopularTab extends Component { //这里是Tab 的名字 static defaultProps = { tabLabel: 'android',} // 构造 constructor(props) { super(props); // 初始状态 this.state = { dataSource: new ListView.DataSource({rowHasChanged: (r1,r2) => r1 !== r2}),//是一个优化,节省无用的UI渲染 判断前后数据是否改变 如果改变就更新 isLoading: true }; } /*componentDidMount() { /!*this.setState({ dataSource: this.state.dataSource.cloneWithRows(['first','second','three']) } )*!/ this.loadData(); };*/ //和上面一样的效果 componentDidMount = () => {
this.loadData();
}
//渲染ListView的每一行
renderRow = (obj) => {
return <ProjectRow item={obj}></ProjectRow>
// return <Text>{obj.full_name}</Text>
}
//加载数据
loadData = () => {
this.setState({isLoading: true});
fetch(`https://api.github.com/search/repositories?q=${this.props.tabLabel}&sort=stars`)
.then(response => response.json()) //服务器响应response对象,继续变成json对象
.then(json => {
//更新dataSource
this.setState({
dataSource: this.state.dataSource.cloneWithRows(json.items),isLoading: false,});
})
.catch((error) => { console.error(error); }).done(); } handleRefresh = () => {
this.loadData();
}
render() {
return <View style={styles.container}>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
refreshControl={
<RefreshControl
refreshing={this.state.isLoading}
tintColor="#63B8FF"
title="正在加载..."
titleColor="#63B8FF"
colors={['#63B8FF']}
/>
}
></ListView>
</View>
}
}
const styles = StyleSheet.create({
container: {
flex: 1
}
});
最后的做完的效果图
总结下我这里做了什么:
- 把导航栏抽取出来了,让每个页面的导航栏作为props
使用导航@R_938_404@面
https://reactnavigation.org/docs/intro/
这里是英文文档.
使用步骤 npm install –save react-navigation
需要先引入这个 react-navigation
可以看到英文文档有三个导航器 那么我这里只需要用到其中一个StackNavigator 堆导航 类似android的activity栈
具体看下我的另一篇blog http://www.jb51.cc/article/p-yhkxreke-bny.html
写的是基础 使用 我这里需要使用自定义的导航
看过文章后应该知道需要把所有的@R_938_404@面在一个js里面定义一次,如果想使用自定义的导航那么需要把navigation
每个页面都传递让每个页面都持有naviagation.这样才能进行页面的跳转
下面说下我是怎么操作的
- 首先因为ios 和android 的index.js 的文件内容都差不多那么就把相同的部分抽取出来 抽取成一个Setup.js,然后在index.android.js 和index.ios.js里面调用
- 在Setup.js中 使用ReactNaviation,使用这个导航器 需要把所有需要跳转的页面在这里定义
下面上代码
这里是index.android.js
/** * Sample React Native App * https://github.com/facebook/react-native * @flow */
import React,{Component} from 'react';
import {
AppRegistry,Image
} from 'react-native';
import SetUp from './js/pages/Setup';
export default class MyApp extends Component {
render() {
return (
<SetUp/>
);
}
}
AppRegistry.registerComponent('testP',() => MyApp);
这是Setup.js 注意在所有的ReactNative中的控件首字母必须大写.不然会出错
/** * Created by liuml on 2017/9/17. */
import React,Platform
} from 'react-native';
import {StackNavigator} from 'react-navigation';
import Homepage from "./HomePage";
import MyPage from "../my/MyPage";
import CustomKeyPage from "../my/CustomKeyPage";
//各个页面路由配置
const RouteConfigs = {
Home: {//首页
screen: Homepage,MyPage: {//我的
screen: MyPage,CustomKeyPage: {//自定义分类
screen: CustomKeyPage,}
//导航器的配置,包括导航器的初始页面、各个页面之间导航的动画、页面的配置选项等等
const NavigatorConfig = {
initialRouteName: 'Home',// 默认显示界面
headerMode: 'none',//https://reactnavigation.org/docs/navigators/stack#StackNavigatorConfig
}
//导航注册
const RootNavigator = StackNavigator(RouteConfigs,NavigatorConfig);
export default RootNavigator;
这里需要解释下StackNavigator 是用于跳转的导航 在他的配置中 如果没有
headerMode: ‘none’ 参数会有自己默认的导航条 这里的意思就是隐藏默认的导航条
还有一些其他的参数看下我的注释和我之前写的一篇文章http://www.jb51.cc/article/p-yhkxreke-bny.html 就应该明白了
自定义ReactNativiation跳转
我现在需要做的是在<我的>页面进行跳转,跳转到<自定义分类>页面.
上代码
/** * Created by liuml on 2017/9/16. */
import React,RefreshControl
}from 'react-native';
import NavigationBar from "../compoent/NavigationBar";
/** * 我的页面 */
export default class MyPage extends Component {
//navigation 里的方法有navigate 是用于页面跳转 goBack是用于页面返回
render() {
const navigation = this.props.navigation.navigate;
return <View style={styles.container}>
<NavigationBar
title="我的"/>
<View style={{flexDirection: 'column',marginTop: 30}}>
<Text onPress={() => {
navigation('CustomKeyPage',{source: '自定义分类'});
}}>自定义分类</Text>
</View>
</View>
}
}
const styles = StyleSheet.create({
container: {
flex: 1
}
})
可以看到我使用navigation 进行跳转 注意这个navigation 是从HomePage.js初始的
时候就有的,我把这个navigation 从HomePage传到了这个MyPage.js 页面 下面是传递的代码
因为HomePage.js 只改了传递参数的代码 我就只截取这一点代码 我参数传递是通过
es6语法 遍历传递的 三个点表示每一个参数一个个的传过去
<TabNavigator.Item
selected={this.state.selectedTab === 'my'}
slectedTitleStyle={{color: '#0F0'}}
renderIcon={() => <Image style={styles.icon}
source={require('../../res/images/ic_my.png')}/>}
renderSelectedIcon={() =>
<Image style={[styles.icon,{tintColor: '#63B8FF'}]}
source={require('../../res/images/ic_my.png')}/>}
onPress={() => this.setState({selectedTab: 'my'})}
title="我的">
<MyPage {...this.props}/>
</TabNavigator.Item>
可以看到主要就是这个代码起作用
<MyPage {...this.props}/>
-自定义分类页面
/** * Created by liuml on 2017/9/17. */
import React,TouchableOpacity
} from 'react-native';
/** * 自定义分类页面 */
import NavigationBar from '../compoent/NavigationBar'
export default class CustomKeyPage extends Component {
handleBack = () => {
this.props.navigation.goBack();
}
getLeftBtn = () => {
return <View style={{flexDirection: 'row',alignItems: 'center'}}>
<TouchableOpacity
activeOpacity={0.7}
onPress={this.handleBack}>
<Image source={require('../../res/images/ic_arrow_back_white_36pt.png')}
style={{width: 24,height: 24}}/>
</TouchableOpacity>
</View>;
}
getRightBtn = () => {
return <View style={{flexDirection: 'row',alignItems: 'center'}}>
<TouchableOpacity activeOpacity={0.7}>
<View style={{marginRight: 10}}>
<Text style={{fontsize: 16,color: '#FFF'}}>保存</Text>
</View>
</TouchableOpacity>
</View>
}
render() {
return <View style={styles.container}>
<NavigationBar
title="自定义分类"
rightButton={this.getRightBtn()}
leftButton={this.getLeftBtn()}/>
<Text onPress={() => {
this.handleBack();
}}>CustomKeyPage</Text>
</View>
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},});
注意我这里是怎么返回的
this.props.navigation.goBack();
navigation有goBack()方法 点击箭头后调用 下面来一张最终的效果图
github 地址 还没写完会继续更新