React native login, signup and navigation 风格二

react

创建react-native项目 ------ zigoo

myths-Mac:~ myth$ react-native init zigoo 

myths-Mac:~ myth$ cd /Home/myth/zigoo && yarn add  react-navigation

App.js 代码文件内容:

import React, { Component } from 'react';
import {
AppRegistry,
View,
Text,
StyleSheet,
ScrollView,
TouchableOpacity
} from 'react-native';
import { StackNavigator } from 'react-navigation';

import HomeScreen from './src/components/Home';
import Login from './src/components/Login';
import Register from './src/components/Register';
import Profile from './src/components/Profile';

const MyApp = StackNavigator({
    Home: { screen: HomeScreen },
    Login: { screen: Login },
    Register: {screen: Register},
    Profile: {screen: Profile}

 });
export default MyApp;

AppRegistry.registerComponent('MyApp', () => MyApp);

src/components/Home.js 代码文件内容:

import React, { Component } from 'react';
import {
AppRegistry,
View,Text,
StyleSheet,
Button,
TouchableOpacity,
StatusBar,
Image
} from 'react-native';

export default class Home extends Component{
    static navigationOptions= ({navigation}) =>({
        title: 'Welcome',
    });
    render(){
        const { navigate } = this.props.navigation;
        return(
            <View style={styles.container}>
            <Text style={styles.pageName}>User Login</Text>
            <TouchableOpacity
                onPress={() => navigate('Login')}
                style={styles.btn1}>
                <Text style={styles.btnText}>Login</Text>
            </TouchableOpacity>
            <TouchableOpacity
                onPress={()=> navigate('Register')}
                style={styles.btn2}>
                <Text style={styles.btnText}>Register</Text>
            </TouchableOpacity>
            </View>
        );
    }
}
const styles = StyleSheet.create({
    container:{
        display:'flex',alignItems:'center',
        justifyContent:'center'
    },
    btn1:{
        backgroundColor:'orange',
        padding:10,margin:10,width:'95%'
    },
    btn2:{
        backgroundColor:'blue',
        padding:10,margin:10,width:'95%'
    },
    pageName:{
        margin:10,fontWeight:'bold',
        color:'#000', textAlign:'center'
    },
    btnText:{
        color:'#fff',fontWeight:'bold'
    },

});

AppRegistry.registerComponent('Home', () => Home);

src/components/Register.js 代码文件内容:

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,Button,TextInput,TouchableOpacity
} from 'react-native';

export default class Register extends Component {
    static navigationOptions= ({navigation}) =>({
      title: 'Register',
      headerRight:
      <TouchableOpacity
        onPress={() => navigation.navigate('Home')}
        style={{margin:10,backgroundColor:'orange',padding:10}}>
        <Text style={{color:'#ffffff'}}>Home</Text>
      </TouchableOpacity>

    });
    constructor(props){
        super(props)
        this.state={
            userName:'',
            userEmail:'',
            userPassword:''
        }
    }
    userRegister = () =>{
        const {userName} = this.state;
        const {userEmail} = this.state;
        const {userPassword} = this.state;
        fetch('http://mo.com/register', {
            method: 'POST',
            headers:{
                'Accept': 'application/json',
                'Content-type': 'application/json'
            },
            body:JSON.stringify({
                name: userName,
                email: userEmail,
                password: userPassword,
            })
        })
         .then((response) => response.json())
         .then((responseJson) =>{
            alert(responseJson);
         })
         .catch((error)=>{
            console.error(error);
         });
    }

  render() {
    return (
        <View style={styles.container}>
            <TextInput
              placeholder="Enter Name"
              style={{width:250,margin:10, borderColor:"#333",
              borderWidth:1}}
              underlineColorAndroid="transparent"
              onChangeText= {userName => this.setState({userName})}
            />
            <TextInput
              placeholder="Enter Email"
              style={{width:250,margin:10, borderColor:"#333", borderWidth:1}}
              underlineColorAndroid="transparent"
              onChangeText= {userEmail => this.setState({userEmail})}
            />
            <TextInput
              placeholder="Enter Password"
              style={{width:250,margin:10, borderColor:"#333", borderWidth:1}}
              underlineColorAndroid="transparent"
              onChangeText= {userPassword => this.setState({userPassword})}
            />
            <TouchableOpacity
            onPress={this.userRegister}
            style={{width:200,padding:10, backgroundColor:'#3d6dcc',
            alignItems:'center'}}>
            <Text style={{color:'#fff'}}>Signup</Text>
            </TouchableOpacity>
         </View>

   );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

AppRegistry.registerComponent('Register', () => Register);

src/components/Login.js 代码文件内容:

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,TouchableOpacity,TextInput,Button,Keyboard
} from 'react-native';
import { StackNavigator } from 'react-navigation';

export default class Login extends Component {
    static navigationOptions= ({navigation}) =>({
          title: 'Login',
          headerRight:
          <TouchableOpacity
            onPress={() => navigation.navigate('Home')}
            style={{margin:12,backgroundColor:'orange',padding:12}}>
            <Text style={{color:'#ffffff'}}>Home</Text>
          </TouchableOpacity>

    });
    constructor(props){
        super(props)
        this.state = {
            userEmail:'',
            userPassword:''
        }
    }

    login = () => {
        const { userEmail, userPassword } = this.state;
        let reg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/ ;
        if(userEmail == "") {
            this.setState({email:'Please enter Email address'})
        } else if(reg.test(userEmail) === false) {
            this.setState({email:'Email is incorrect'})
            return false;
        } else if(userPassword=="") {
            this.setState({email:'Please enter Password'})
        } else {
            fetch('http://mo.com/login',{
               method: 'POST',
               headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
               },
               body: JSON.stringify({ email: userEmail, password: userPassword })
            })
             .then((response) => response.json())
             .then((responseJson) => {
                 if(responseJson == "ok"){
                     // redirect to profile page
                     alert("Login successfully");
                     this.props.navigation.navigate("Profile");
                 }else{
                     alert("Login failed");
                 }
             })
             .catch((error) => {
                 console.error(error);
             });
        }
        Keyboard.dismiss();
}

  render() {
    return (
        <View style={styles.container}>
            <Text style={{padding:10,margin:10,color:'red'}}>{this.state.email}</Text>
            <TextInput
                placeholder="Enter Email"
                style={{width:250,margin:10, borderColor:"#333", borderWidth:1}}
                underlineColorAndroid="transparent"
                onChangeText={userEmail => this.setState({userEmail})}
            />
            <TextInput
                placeholder="Enter Password"
                style={{width:250,margin:10, borderColor:"#333", borderWidth:1}}
                underlineColorAndroid="transparent"
                onChangeText={userPassword => this.setState({userPassword})}
            />
            <TouchableOpacity
                onPress={this.login}
                style={{width:200,padding:10,backgroundColor:'#3d6dcc',alignItems:'center'}}>
                <Text style={{color:'white'}}>Login</Text>
            </TouchableOpacity>
         </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },

});

AppRegistry.registerComponent('Login', () => Login);

src/components/Profile.js 代码文件内容:

import React, { Component } from 'react';
import { AppRegistry,View,Text,StyleSheet } from 'react-native';

export default class Profile extends Component{
    static navigationOptions= ({navigation}) =>({
        title: 'Welcome',
    });
    render(){
        const { navigate } = this.props.navigation;
        return(
          <View style={styles.container}>
            <Text style={styles.pageName}>Profile</Text>
          </View>
        );
    }
}
const styles = StyleSheet.create({
    container:{
        display:'flex',alignItems:'center',
        justifyContent:'center'
    },
    pageName:{
        margin:10,fontWeight:'bold',
        color:'#000', textAlign:'center'
    },
});

AppRegistry.registerComponent('Profile', () => Profile);

单向数字证书
[[email protected] ~]# openssl genrsa -out ca-app.key 2048    ## 1). 生成一个CA私钥
Generating RSA private key, 2048 bit long modulus
.......................................................................................................................................................+++
..........+++
e is 65537 (0x10001)
[[email protected] ~]# openssl req -x509 -new -nodes -key ca-app.key -days 365 -out ca-app.crt   ## 2).使用ca-app私钥生成客户端的数字证书
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:GuangDong
Locality Name (eg, city) [Default City]:ShenZhen
Organization Name (eg, company) [Default Company Ltd]:ZiGoo
Organizational Unit Name (eg, section) []:                    ## 直接按回车键跳过
Common Name (eg, your name or your server's hostname) []:mo.com
Email Address []:[email protected]
[[email protected] ~]# cp ca-app.key  /etc/pki/tls/private/
[[email protected] ~]# cp ca-app.crt  /etc/pki/tls/certs/
私钥文件   ca-app.key
数字证书   ca-app.crt

直接在httpd.conf配置文件查看apache执行用户和执行组,在以下红色字体标识的66行和67行即是用户和用户组,我们要把第66行和第67行改成如下的样子,其中myth是我登录CentOS 7.2系统的用户名

[[email protected] ~]$ cat -n /etc/httpd/conf/httpd.conf    #用此行命令查看httpd.conf文件的内容,注意我们要编辑的66和67行

   第66行  User myth

   第67行  Group myth


配置Apache服务器:

[[email protected] ~]$ cat > /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.123.198   mo.com

[[email protected] ~]$ cat > /etc/httpd/conf.d/httpd-vhosts.conf

<Directory "/home/myth/www/moapp">
        Options +Indexes +FollowSymLinks
        Order allow,deny
        Allow from all
        AllowOverride All
        Require all granted
</Directory>
<VirtualHost *:80>
    ServerAdmin [email protected]
    DocumentRoot "/home/myth/www/moapp/public"
    ServerName mo.com
    ServerAlias mo.com
    ErrorLog "/home/myth/log/httpd/mo-com-error_log"
    CustomLog "/home/myth/log/httpd/mo-com-access_log" common
</VirtualHost>
<Directory "/home/myth/www/moapp">
        Options +Indexes +FollowSymLinks
        Order allow,deny
        Allow from all
        AllowOverride All
        Require all granted
</Directory>
<VirtualHost *:443>
    SSLEngine on                
    SSLCertificateFile /etc/pki/tls/certs/ca-app.crt                           
    SSLCertificateKeyFile /etc/pki/tls/private/ca-app.key                        
    # SSLCertificateChainFile /etc/pki/tls/certs/ca-app.pem
    ServerAdmin [email protected]
    DocumentRoot "/home/myth/www/moapp/public"
    ServerName mo.com
    ServerAlias mo.com
    ErrorLog "/home/myth/log/httpd/mo-com-s-error_log"
    CustomLog "/home/myth/log/httpd/mo-com-s-access_log" common
</VirtualHost>

[[email protected] ~]$ su -
Password:
Last login: Mon Apr  2 14:11:31 CST 2018 on pts/1
[[email protected] ~]#  lsof -i:80
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
httpd    1069 root    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd    1315 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd    1316 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd    1317 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd    1318 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd    1319 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd    2860 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd   18468 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd   18688 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
[[email protected] ~]# systemctl restart httpd  && systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2018-04-03 23:44:21 CST; 13ms ago
     Docs: man:httpd(8)
           man:apachectl(8)
  Process: 47406 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=0/SUCCESS)
 Main PID: 47415 (httpd)
   Status: "Processing requests..."
   CGroup: /system.slice/httpd.service
           ├─47415 /usr/sbin/httpd -DFOREGROUND
           ├─47416 /usr/sbin/httpd -DFOREGROUND
           ├─47417 /usr/sbin/httpd -DFOREGROUND
           ├─47419 /usr/sbin/httpd -DFOREGROUND
           ├─47420 /usr/sbin/httpd -DFOREGROUND
           └─47421 /usr/sbin/httpd -DFOREGROUND

Apr 03 23:44:21 contoso.org systemd[1]: Starting The Apache HTTP Server...

Apr 03 23:44:21 contoso.org systemd[1]: Started The Apache HTTP Server.


配置macOS系统的hosts文件 ------ macOS这台机器是react-native这台开发机器

myths-Mac:~ myth$ sudo su

Password:
sh-3.2# cat > /etc/hosts
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1    localhost
255.255.255.255    broadcasthost
::1             localhost
192.168.123.198  mo.com

接下来我们要在macOS系统的命令行终端里通过命令去修改Android手机模拟器它的操作系统对应的hosts文件,修改它就有点特别啦,请按我的顺序执行指令,注意可能你的设备名称显示出来跟我的不一样,你需要开启两个终端窗口,一个用来首先用来启动安卓模拟用的,另外一个用来修改hosts文件用的,请特别注意192.168.123.198这个IP改成你实际的IP地址,本范例是在VMWare workstation pro 12 中实验的 1台PHP部署环境 用的系统是CentOS 7.2 另外一台开发react-native的机器是macOS系统

如果你已经有安卓模拟打开了 就必须关闭它们,那我们先来用命令以可写信息的模式来启动安卓模拟器吧:

电脑macOS系统中的命令终端窗口1,你发现自己emulator命令不是全局目录命令,

请参考我其它篇幅中讲的1条指令搞定配置部分

myths-Mac:~ emulator -list-avds  #列出所有模拟器

Nexus_5X_API_23

myths-Mac:~ emulator -avd Nexus_5X_API_23 -writable-system  #以可写信息的模式来启动安卓模拟器

电脑macOS系统中的命令终端窗口2,开始修改手机的hosts文件

myths-Mac:~ myth$ adb shell cat /etc/hosts

127.0.0.1       localhost
::1             ip6-localhost
myths-Mac:~ myth$ adb root
adbd is already running as root
myths-Mac:~ myth$ adb remount
remount succeeded
myths-Mac:~ myth$ adb pull /system/etc/hosts ~/Desktop/hosts
/system/etc/hosts: 1 file pulled. 0.0 MB/s (56 bytes in 0.003s)
myths-Mac:~ myth$ echo '192.168.123.198  mo.com' >> ~/Desktop/hosts
myths-Mac:~ myth$ cat ~/Desktop/hosts
127.0.0.1       localhost
::1             ip6-localhost

192.168.123.198  mo.com
myths-Mac:~ myth$ adb push ~/Desktop/hosts /system/etc/hosts
/Users/myth/Desktop/hosts: 1 file pushed. 0.0 MB/s (81 bytes in 0.005s)
myths-Mac:~ myth$ adb shell cat /etc/hosts
127.0.0.1       localhost
::1             ip6-localhost

192.168.123.198  mo.com

myths-Mac:~ myth$

[[email protected] ~]# exit  #如果你的命令是root用户模式,请一定要退出root模式
logout
[[email protected] ~]$

创建基于ThinkPHP 5.1 框架PHP项目 ------ moapp,退出root账户的命令模式环境安装框架并创建moapp项目:

[[email protected] ~]$ cd /home/myth/www && composer create-project topthink/think moapp --prefer-dist

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `email` varchar(30) DEFAULT NULL,
  `password` varchar(36) DEFAULT NULL,
  `mobile` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8

配置路由:

/home/myth/www/moapp/route/route.php

<?php
Route::post('login', 'index/Login/signin');               // POST   http://mo.com/login
Route::post('register', 'index/Register/signup');         // POST   http://mo.com/register
return [
];

实现控制器方法:

/home/myth/www/moapp/application/index/controller/Register.php

<?php
namespace app\index\controller;
use think\Controller;
use think\Request;
use think\Db;

class Register extends Controller {
    public function signup(Request $request) {
        $name = $request->param('name');
        $email = $request->param('email');
        $password = md5($request->param('password'));
        $user = ['name' => $name, 'email' => $email, 'password' => $password];
        // 启动事务
        Db::startTrans();
        try {
            $count = Db::name('users')->where(['email' => $email])->count('id');
            if ($count == 0) {
                Db::name('users')->insert($user);
            }
            // 提交事务
            Db::commit();
            if ($count == 0) {
                return json('Registered Successfully');
            } else {
                return json('E-mail already exist');
            }
        } catch (Exception $ex) {
            // 回滚事务
            Db::rollback();
            return json('signup failed');
        }
    }

}

/home/myth/www/moapp/application/index/controller/Login.php

<?php
namespace app\index\controller;
use think\Controller;
use think\Request;
use think\Db;

class Login extends Controller {
    public function signin(Request $request) {
        $email = $request->param('email');
        $password = md5($request->param('password'));
        // 启动事务
        Db::startTrans();
        try {
            $count = Db::name('users')
                    ->where(['email' => $email])
                    ->where(['password' => $password])
                    ->count('id');
            // 提交事务
            Db::commit();
            if ($count == 0) {
                return json('login failed');
            } else {
                return json('ok');
            }
        } catch (Exception $ex) {
            // 回滚事务
            Db::rollback();
            return json('login failed');
        }
    }

}

补充强调:模拟器必须用以下方式启动,开发工具上的启动方式启动安卓模拟器会立刻闪退,一旦模拟器被删掉,配置的手机hosts文件就立即被删掉

myths-Mac:~ emulator -list-avds  #列出所有模拟器

Nexus_5X_API_23      

以此处显示的Nexus_5X_API_23是模拟器的实际名称,我们可以用它来启动模拟器,当你发现开发工具上的模拟器按钮无法启动模拟器时,必须删除这个模拟重新创建一个新的模拟即可启动了,当然安卓手机的hosts文件也就恢复到了默认值 ------ 你配置的IP到域名映射关系就不存在啦

myths-Mac:~ emulator -avd Nexus_5X_API_23 -writable-system  #以可写信息的模式来启动安卓模拟器

以上是 React native login, signup and navigation 风格二 的全部内容, 来源链接: utcz.com/z/382603.html

回到顶部