手机导航栏
RN
中主要用于自定义组件属性的类型限定
,或者叫做属性确认
,当外部传入非法的属性类型,会有警告(不是IDE,而是控制台)。PropTypes
定义的属性,会有提示。(然而我试了Atom & WebStorm,IDE并没有提示)在React v15.5
,PropTypes
被从react库
中拿了出来,单独放在了一个名为prop-types
的库中.
React v15.5
之前,PropTypes
属于react库
.
$ import { PropTypes } from ‘react’;
React v15.5
开始,react库
移除了PropTypes
,转而使用prop-types库
替代.
$ import PropTypes from ‘prop-types’;
使用方式
React v15.5`之前
static propTypes = {
autoPlay: React.PropTypes.bool.isRequired,
maxLoops: React.PropTypes.number.isRequired,
}; // 注意这里有分号
React v15.5
开始
static propTypes = {
autoPlay: PropTypes.bool.isRequired,
maxLoops: PropTypes.number.isRequired,
}; // 注意这里有分号
PropTypes从react库移除之后,会导致老项目报错(属性找不到).
RN的版本更新很快,目前已经是0.51.0,随着React Native的升级,系统废弃了很多的东西,过去我们可以直接使用 React.PropTypes来进行属性确认,不过这个自React v15.5起就被移除了,转而使用prop-types库来进行替换.
为了保证RN代码高效运行,属性确认仅在开发环境中有效,正式发布的 App 运行时是不会进行检查的.
import React, {Component} from 'react';
import {View, Text,StyleSheet} from 'react-native';
import Girl from './Girl';
import NavigationBar from './NavigationBar';
export default class Boy extends Component {
constructor(props) {
super(props);
this.state = {
what:''
};
}
render() {
let what = this.state.what===''?'':'我收到了女孩回赠的:' + this.state.what;
return (
<View style={styles.container}>
<NavigationBar
title='Boy'
style = {{
backgroundColor:'red',
}}
/>
<Text style={styles.tips}>I am boy</Text>
<Text style={styles.tips}
onPress={()=>{
this.props.navigator.push({
component:Girl,
params:{
what: '一支玫瑰',
onCallBack:(what) => {
this.setState({
what:what ,
});
}
}
})
}}
>送女孩一支玫瑰</Text>
<Text style={styles.text}>{this.state.word}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'gray',
},
tips: {
fontSize: 29,
}
});
import React, {Component } from 'react';
import PropTypes from 'prop-types';
import {View, Text, StyleSheet, Image, Platform,StatusBar} from 'react-native';
const NAV_BAR_HEIGHT_ANDROID = 50;
const NAV_BAR_HEIGHT_IOS = 44;
const STATUS_BAR_HEIGHT = 20;
const StatusBarShape = {
backgroundColor:PropTypes.string,
barStyle:PropTypes.oneOf(['default','light-content', 'dark-content']),
hidden:PropTypes.bool
}
export default class NavigationBar extends Component {
static propTypes = { // 指定属性的约束
style:PropTypes.style,
title:PropTypes.string,
titleView:PropTypes.element, // 设置 titileView 为元素
hide:PropTypes.bool,// 设置鼠标隐藏
leftButton:PropTypes.element, // 左右侧按钮
rightButton:PropTypes.element,
statusBar: PropTypes.shape(StatusBarShape) // 允许用户指定状态栏,约束形状
}
static defaultProps = {
statusBar:{
barStyle:'light-content',
hidden:false
}
}
constructor(props) {
super(props);
this.state = {
title:'',
hide:false
};
}
render() {
let status = <View style={[styles.statusBar,this.props.statusBar]}>
<StatusBar {...this.props.statusBar}/>
</View>
let titleView = this.props.titleView?this.props.titleView:
<Text style={styles.title}>{this.props.title}</Text>
let content = <View style={styles.navBar}>
{this.props.leftButton}
<View style={styles.titleViewContainer}>
{titleView}
</View>
{this.props.rightButton}
</View>
return (
<View style={[styles.container, this.props.style]}>
{status}
{content}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'gray',
},
navBar:{
justifyContent:'space-between',// 两侧空格
alignItems:'center', // 文字居中显示
height:Platform.OS ==='ios' ?NAV_BAR_HEIGHT_IOS :NAV_BAR_HEIGHT_ANDROID,// 指定高度
// backgroundColor: 'red',
flexDirection:'row'// 文字显示在一排
},
titleViewContainer:{
justifyContent:'center',
alignItems:'center',
position:'absolute',
left:40,
right:40,
top:0,
bottom:0
},
title:{
fontSize:20,
color:'white'
},
statusBar:{
height:Platform.OS ==='ios' ?STATUS_BAR_HEIGHT :0,// 指定高度
}
});
TouchableOpacity 包裹 前进/后退箭头的组件
import React, {Component} from 'react';
import {View, Text, Image, StyleSheet,TouchableOpacity} from 'react-native';
import NavigationBar from './NavigationBar';
export default class Girl extends Component {
// 封装左右侧代码
renderButton(image){
return <TouchableOpacity
onPress={()=>{
this.props.navigator.pop() // 点击按钮时关闭当前窗口
}}
>
<Image style={{width:22,height:22,margin:5}} source={image}></Image>
</TouchableOpacity>
}
render() {
return (
<View style={styles.container}>
<NavigationBar
title='Girl'
style = {{
backgroundColor:'#EE6363',
}}
leftButton={
this.renderButton(require('./res/images/ic_arrow_back_white_36pt.png'))
}
rightButton={
this.renderButton(require('./res/images/ic_star.png'))
}
/>
<Text style={styles.text}>I am girl</Text>
<Text style={styles.text}>我收到了男孩送的:{this.props.what}</Text>
<Text style={styles.text}
onPress={()=>{
this.props.onCallBack('一盒巧克力')
this.props.navigator.pop()
}}
>回赠巧克力</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
// justifyContent:'center'
},
text: {
fontSize: 22,
}
});
如何自定义NavigationBar?
创建js文件(组件): 放NavigationBar
设置属性的默认属性 , propTypes
渲染组件的结构
render() { let status =
let titleView = this.props.titleView?this.props.titleView: {this.props.title} let content ={this.props.leftButton} return ({titleView} {this.props.rightButton}{status} {content} ); } }安卓IOS,指定高度
height:Platform.OS ==='ios' ?STATUS_BAR_HEIGHT :0,// 指定高度
对组件整体的把控, 以及将来总体上的应用都有一定要求,如果感觉比较难,请学过几章后回头看看.?
对函数的封装,节省了代码,使结构清晰
- return,使用
- 将图片作为参数传入
精彩!
leftButton={ this.renderButton(require('./res/images/ic_arrow_back_white_36pt.png')) } rightButton={ this.renderButton(require('./res/images/ic_star.png')) } // 封装左右侧代码 renderButton(image){ return <TouchableOpacity onPress={()=>{ this.props.navigator.pop() // 点击按钮时关闭当前窗口 }} > <Image style={{width:22,height:22,margin:5}} source={image}></Image> </TouchableOpacity> }