React Native 导航(Navigator)详解——实例二

这个例子主要是展示页面间的参数传递,以及简要说明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值

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值