这个例子主要是展示页面间的参数传递,以及简要说明ES6的新语法的使用。分为两个页面:注册页、设置初始密码页。操作流程是:在注册页输入名字 》点击提交,把输入的名字传到第二页设置初始密码页 》在初始密码页显示姓名,并点击初始化密码按钮设置初始密码 》把初始化密码传入到第一页注册页 》隐藏注册框和按钮,显示名字和密码,并修改页面标题。效果图如下:
代码分为三部分,index.js、registerFirst.js、registerSecond.js,index作为导航页面的主入口,用于加载页面。registerFirst为第一页,registerSecond为第二页。要了解的知识有React(React Native是基于React.js)的state属性、props属性,以及state和props用法上的区别;ES6新增语法的使用;下面对关键代码进行说明:
1》index.js导航入口页
/**
* Created by linyufeng on 2016/9/4.
*/
import React, {Component} from 'react';
import {AppRegistry, Navigator} from 'react-native';
import registerFirst from './registerFirst';
const defaultRoute = {component: registerFirst};
export default class MyProject extends Component {
render() {
return (
Navigator.SceneConfigs.HorizontalSwipeJump }
renderScene={(route, navigator) => {
let Component = route.component;
return (
);
}
}
/>
);
}
}
AppRegistry.registerComponent('MyProject', () => MyProject);
源码分析:
import registerFirst from './registerFirst';
引入注册页面,注册页面定义为一个Component组件,通过import引入进来。用法和代码前两句是一模一样的,加载模块。
const defaultRoute = {component: registerFirst};
定义静态常量defaultRoute,定义的component对象就是第一个页面registerFirst。
initialRoute={defaultRoute}
初始化路由,显示的第一个页面
configureScene={(route, routeStack) => Navigator.SceneConfigs.HorizontalSwipeJump }
定义页面切换动画
renderScene={(route, navigator) => {
<span style="white-space:pre"> </span>let Component = route.component;
<span style="white-space:pre"> </span>return (
<span style="white-space:pre"> </span><Component {...route.params} navigator={navigator} />
<span style="white-space:pre"> </span>);
}}
定义页面渲染,传入的两个参数route和navigator,route就是initialRoute里面的那个路由(页面),navigator就是当前的navigator对象。
let Component = route.component;
在路由中取出component对象,let是ES6新增数据类型,用法和var一样,区别是var会带来变量作用域提升,并且通过var对象定义的this会脱离定义时环境而指向运行时的环境,详细语法说明和示例可以参看http://es6.ruanyifeng.com/
<Component {...route.params} navigator={navigator} />
这句代码非常关键,对于新手来说也非常难以理解。
ES6引入rest参数(形式为“...变量名”),用于获取函数的多余参数。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中;和扩展运算符(spread)是三个点(...)。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。
rest例子
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;}
add(2, 5, 3) // 10
spread 例子
console.log(...[1,2,3])
//1,2,3
先不要管route.params从哪来,看下面的例子:
let params = {a:1, b:2};
return (
<Component {...params} navigator={navigator} />
);
等同于
return (
<Component a={1} b={2} navigator={navigator} />
);
看这个你就可以看明白了吧,上边的{...params}就是把参数对象所有属性都转化成为组件的props属性,组件就可以获得传递过来的参数,完成参数传递的过程。Route.params的定义在第一个页面注册页
let scenes = {
component: registerSecond,
params: {
name: _this.state.name,
setPassword: (password)=> {
_this.setState({password: password});
}
}
};
2》registerFirst.js注册页面
/**
* Created by linyufeng on 2016/9/4.
*/
import React, {Component} from 'react';
import {Text, TextInput, View, ToastAndroid, TouchableOpacity} from 'react-native';
import registerSecond from './registerSecond';
export default class registerFirst extends Component {
constructor(props) {
super(props);
this.state = {
name: null
}
}
//页面跳转
_push() {
let _this = this;
const {navigator} = this.props;
let scenes = {
component: registerSecond,
params: {
name: _this.state.name,
setPassword: (password)=> {
_this.setState({password: password});
}
}
};
navigator.push(scenes);
}
render() {
if (this.state.password) {
return (
注册成功
欢迎 {this.state.name},您的初始密码为:{this.state.password}
);
} else {
return (
注册
this.setState({ name })}/>
提交
);
}
}
}
const styles = {
navGroup: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#495A80',
height: 60,
paddingHorizontal: 5
},
title: {
color: '#fff', fontSize: 16, textAlign: 'center'
},
text: {
color: '#495A80', fontSize: 14, textAlign: 'center'
},
scenes: {
flex: 1
},
btn: {
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: '#495A80',
borderRadius: 5,
margin: 5,
padding: 10
}
};
源码分析:
this.state = { name: null }
初始化state的name变量
let _this = this;
ES6语法,let拿到this指引,并在当前{}内锁定对象引用
const {navigator} = this.props;
ES6语法,对象的解构赋值
var { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
此处navigator就是拿到组件props中的Navigator对象,定义处在index.js的
<Component {...route.params} navigator={navigator} />
params: {
name: _this.state.name,
setPassword: (password)=> {
_this.setState({password: password});
}
}
定义params参数,进行页面间的参数传递。此处的_this不能用this代替(查看ES6中let用法),params里面定义的属性和方法都会变为组件的props属性,进行传递。
navigator.push(scenes);
添加第二个页面,设置初始化密码页面
if (this.state.password) { ... } else { ... }
这里面做了个判断,通过是否有password值来显示不同的view
onChangeText={name => this.setState({ name })}/>
监听输入框值的变化动态修改state里面的name值
<TouchableOpacity style={styles.btn} onPress={this._push.bind(this)}>
这里的bind(this)是必要的,绑定this到当前方法上
3》registerSecond.js设置初始化密码
/**
* Created by linyufeng on 2016/9/4.
*/
import React, {Component} from 'react';
import {Text, View, ToastAndroid, TouchableOpacity} from 'react-native';
export default class registerSecond extends Component {
constructor(props) {
super(props);
this.state = {
name: null
}
}
componentDidMount() {
this.setState({
name: this.props.name
});
}
//设置密码
_setPassword() {
const {navigator} = this.props;
this.props.setPassword('123456');
ToastAndroid.show('设置成功', ToastAndroid.SHORT);
}
//返回
_pop() {
const {navigator} = this.props;
navigator.pop();
}
render() {
return (
< 返回
初始化密码
注册用户名为:{this.state.name}
设置初始密码
);
}
}
const styles = {
navGroup: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: '#495A80',
height: 60,
paddingHorizontal: 5
},
title: {
color: '#fff', fontSize: 16
},
text: {
color: '#495A80', fontSize: 14, textAlign: 'center'
},
scenes: {
flex: 1
},
btn: {
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: '#495A80',
borderRadius: 5,
margin: 5,
padding: 10
}
};
componentDidMount() {
this.setState({
name: this.props.name
});
}
React 组件生命周期
组件的生命周期可分成三个状态:
· Mounting:已插入真实 DOM
· Updating:正在被重新渲染
· Unmounting:已移出真实 DOM
生命周期的方法有:
componentWillMount 在渲染前调用,在客户端也在服务端。
componentDidMount : 在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异部操作阻塞UI)。
componentWillReceiveProps 在组件接收到一个新的prop时被调用。这个方法在初始化render时不会被调用。
shouldComponentUpdate 返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。
可以在你确认不需要更新组件时使用。
componentWillUpdate在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
componentDidUpdate 在组件完成更新后立即调用。在初始化时不会被调用。
componentWillUnmount在组件从 DOM 中移除的时候立刻被调用。
——来自http://www.runoob.com/react/react-component-life-cycle.html
this.setState({ name: this.props.name });
接收组件的props中的name参数,并设置为state中的name值