【React Native 实战:构建电商 App】09-注册登录

React Native 实战:构建电商 App

这篇内容首先会教大家一个原生在启动 RN 的时候传参数的方法,该方法需要少量的更改原生代码即可,实现非常简单,接着会正式讲解怎么开发一个登录注册界面。

初始化参数传递

加入项目需要用到几个 App 一起上线,但是使用的是一套前端代码,这里就可以通过原生传入参数的方式改变前端的行为,这个方式使用到场景也不算少了,有需要的可以了解一下。

import { AppRegistry } from 'react-native';
import Pages from './src';
//启动
AppRegistry.registerComponent('anxintao', () => Pages);

这就是一段 App 注册启动组件的地方,当原生的方面开始执行 bundle 文件之后就会通知 js 启动anxintao这个已经注册的组件,同时也会将一些参数传入进来,在内部使用 props 的方式可以获取到。

iOS 传参数

iOS 相对比较简单,可以在 iOS 的AppDelegate.m文件中可以看到。

enter image description here

图中的 AppDelegate 其实就是整个 iOS 应用程序的开始部分,这里初始化了一个 RCTRootView 用来渲染 RN 的项目,后面的 moduleName 就是在 js 中注册的 UI 组件;第二行的 initialProperties 就是要传的参数。

//初始化一个不可变字典,传入一个key:value组合。
NSDictionary *props =[NSDictionary dictionaryWithObject:@"test_value" forKey:@"key"];

initialProperties 接受一个字典类型的参数,这里初始化一个 props 变量,固定长度是 1,键名是 key,值是 test_value,然后传入对象即可。

enter image description here

重新运行命令 react-native run-ios 编译一个新的客户端,在页面中即可看到传入的参数已经显示在输出的日志中了。

enter image description here

在页面中要获取可以在根组件中直接访问 props 即可。这里需要注意的是,代码中使用 key 作为键名是不正确的,js 中的 key 是有它自己的含义的,如果使用这个名字的话是获取不到 value 值的,这里我改成了 key 1 就好了。

enter image description here

enter image description here

Android 传参数

Android 的要稍微复杂一些,RN 并没有提供一个简单快捷的方法传参数,打开 Android 的 MainActivity.java 可以看到这个类继承了 RN 的 ReactActivity 类,该类简单的传入了注册的 UI 组件的名字就结束了,返回参数要求是字符串,可见并没有留有传参数的可能性。

enter image description here

我们再进入 ReactActivity 这个类看看这个类的实现方式,这里推荐使用 Android Studio 打开安卓项目,可以非常方便的打开 ReactActivity 做在的文件。

enter image description here

从图中可以很方便的看到这个类主要使用的是一个叫 ReactActivityDelegate 的代理类,js 的事件通知都是用过这个类来实现的,再进入这个类看看它的内部实现。

enter image description here

从这里可以看到,在类创建之后就执行了一个 loadApp 方法,该方法内部创建了一个根视图,并启动了 js 的 UI 组件,启动方法的第三个参数就是传参数的地方。

Android 想要传参数就需要改这个传参数的方法,新建一个类并继承 ReactActivityDelegate,在内部将需要的 getLaunchOptions 方法重新实现就好了。

enter image description here

图中实现了一个自己的 getLaunchOptions 方法,我们传入了 1 个参数,它的值是test_value_android

在 MainActivity 中重载 ReactActivity 的 createReactActivityDelegate 方法,创建一个新变量就可以把我们需要传入的参数传入到 js 中了。

 @Override
    protected ReactActivityDelegate createReactActivityDelegate() {
        //返回刚才新建的类实例
        return new RNActivityDelegate(this, getMainComponentName());
    }

刷新 App 即可看到最新的结果。

enter image description here

登录界面

新建文件 /src/account/login.js,将这个文件放入路由中,这里使用设置中的退出登录作为跳转入口。

logout(){
   this.props.navigation.navigate('Login');
 }

首先根据设计将 UI 界面做好,这里留一个手机登录和一个微信登录。

{/*Logo*/}
            <Image
                source={{ uri: require('../images/logo_new') }}
                style={{ width: px(220), height: px(130), marginTop: px(170), marginLeft: px(50), marginBottom: px(80) }} />
            {/*手机号输入框*/}
            <View style={[styles.input, { marginBottom: px(12) }]}>
                <TextInput style={styles.inputTxt}
                    placeholder='请输入手机号' placeholderTextColor="#b2b3b5"
                    maxlength={11} keyboardType="numeric"
                    clearButtonMode='while-editing'
                    onChangeText={(v) => this.setState({ tel: v })}
                    underlineColorAndroid="transparent" />
            </View>
            {/*短信验证码*/}
            <View style={[styles.input, { marginBottom: px(62) }]}>
                <TextInput style={styles.inputTxt}
                    placeholder='请输入验证码' placeholderTextColor="#b2b3b5"
                    maxLength={10} keyboardType="numeric"
                    onChangeText={(v) => this.setState({ code: v })}
                    underlineColorAndroid="transparent" />
                <Text allowFontScaling={false} style={this.state.sent ? styles.sent : styles.send}
                    onPress={() => this.sendCode()}>
                    {this.state.sent ?
                        `重新获取${this.state.timeout}S` :
                        `获取验证码`
                    }
                </Text>
            </View>
            {/*登录按钮*/}
            <TouchableOpacity activeOpacity={0.8} onPress={() => this.submit()}>
                <View style={[styles.btn, { backgroundColor: '#d0648f' }]}>
                    <Text allowFontScaling={false} style={{ fontSize: px(30), color: '#fff' }}>
                        登录</Text>
                </View>
            </TouchableOpacity>
            {/*微信登录*/}
            <View style={{ position: 'absolute', bottom: px(80) }}>
                <TouchableOpacity style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}
                    activeOpacity={0.8}
                    onPress={() => this.loginWeChat()}>
                    <Image source={{ uri: require('../images/icon-wechat') }} style={{ width: px(38), height: px(38), marginRight: px(13) }} />
                    <Text allowFontScaling={false} style={{ color: '#679d5e', fontSize: px(28) }}>微信登录</Text>
                </TouchableOpacity>
            </View>

点击发送验证码之后会有一个倒计时,这里使用定时器定时更新倒计时的数字。

//倒计时
startTimer() {
    this.setState({
        'sent': Date.now(),
        'timeout': 60
    });
    this.timer = setInterval(() => {
        let elapsed = Math.ceil((Date.now() - this.state.sent) / 1000);
        if (elapsed > 60) {
            this.setState({
                'sent': null,
                'timeout': null
            });
            clearInterval(this.timer);
            delete this.timer;
        } else {
            this.setState({
                'timeout': 60 - elapsed
            });
        }
    }, 100);
}

登录成功之后需要重置整个路由,这里可以设置路由的层级和所处位置,记得将之前的几个页面引用销毁,否则会出现报错甚至页面都已经销毁了,但是方法还在不断执行的问题。

goTabPage() {
        this.props.navigation.dispatch(NavigationActions.reset({
            index: 0,
            actions: [
                NavigationActions.navigate({ routeName: 'Tabs' })
            ]
        }))
    }

发表评论