第08课:注册登录

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

初始化参数传递

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

``` javascrpt 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](http://images.gitbook.cn/cdb22200-1d51-11e8-a5c9-f3312146b989)

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

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

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

![enter image description here](http://images.gitbook.cn/0ca71e10-1d53-11e8-baea-27490b783ebf)

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

![enter image description here](http://images.gitbook.cn/3c400600-1d53-11e8-aae3-bd72b8a3fcfc)

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

![enter image description here](http://images.gitbook.cn/136318c0-1d54-11e8-baea-27490b783ebf)

![enter image description here](http://images.gitbook.cn/f46a7a30-1d53-11e8-aae3-bd72b8a3fcfc)

#### Android 传参数

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

![enter image description here](http://images.gitbook.cn/bfc0ebb0-1d54-11e8-aae3-bd72b8a3fcfc)

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

![enter image description here](http://images.gitbook.cn/4afe0ff0-1d55-11e8-aae3-bd72b8a3fcfc)

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

![enter image description here](http://images.gitbook.cn/a1cca850-1d55-11e8-a5c9-f3312146b989)

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

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

![enter image description here](http://images.gitbook.cn/d6722d40-1d56-11e8-bf2f-bd9af1ed3ee8)

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

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

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

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

![enter image description here](http://images.gitbook.cn/f46a7a30-1d53-11e8-aae3-bd72b8a3fcfc)

### 登录界面

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

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

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

javascript {/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>

<img src="http://images.gitbook.cn/a6236030-22a3-11e8-86f8-33ed71c2b78e"  width = "40%" />

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

javascript //倒计时 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); }

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

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

评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符 “速评一下”
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页