React Native学习之路(9) - 注册登录验证的实现 + (用Fetch实现post请求) + (倒计时验证码)+(父子组件通信)+(asyncStorage异步存储) +(TextInput文本输入框)

(1)TextInput文本输入框

TextInput属性
  • (1) keyboardType :设置键盘类型(决定使用哪种键盘)
'email-address' : 邮箱键盘
 'numeric'  :数字键盘
 'phone-pad' :
  • (2) secureTextEntry :如果为true,文本框会遮住之前输入的文字,这样类似密码之类的敏感文字可以更加安全。默认值为false。( secure安全的意思 ) ( entry输入的意思 )
  • (3) placeholder :在文本输入之前提示用户文本框功能,也就是占位文字
  • (4) placeholderTextColor:占位字符串的文本颜色
  • (5) autoFocus:如果为true,在componentDidMount后会获得焦点。默认值为false。
  • (6) selectionColor :设置输入框高亮时的颜色(在iOS上还包括光标)
  • (6) editable:如果值为假,文本是不可编辑,默认值为真7
  • (7) maxLength :限制文本框中最多的字符数。使用这个属性而不用JS逻辑去实现,可以避免闪烁的现象。
  • (8) multiline:如果值为真,文本输入可以输入多行,默认值为假 ( multiline:多线路的 )
  • (9) onFocus :当文本框 (获得)焦点的时候调用此回调函数。
  • (10) onBlur :当文本框 (失去) 焦点的时候调用此回调函数。
  • (11) onChange:当文本框内容变化时调用此回调函数
  • (12) onChangeText:当文本框内容变化时调用此回调函数。改变后的文字内容会作
    为参数传递
 onChangeText={ (text) => {
                            this.setState({
                                phoneNumber: text   
                            })    //当文本框内容发生改变时,将文本框中输入的字符传给state
                        } }
  • (13) onEndEditing :当文本输入结束后调用此回调函数。
  • (14) inlineImageLef :指定一个图片放置在左侧。
  • (15) androidinlineImagePadding :给放置在左侧的图片设置padding样式。
  • (16) autoCapitalize :控制TextInput是否要自动将特定字符切换为大写:
 'characters': 所有的字符。
 'words': 每个单词的第一个字符。
 'sentences': 每句话的第一个字符(默认)。
' none': 不自动切换任何字符为大写。
  • (17) autoCorrect :如果为false,会关闭拼写自动修正。默认值是true。
  • (18) underlineColorAndroid :文本框的下划线颜色(译注:如果要去掉文本框的边框,请将此属性设为透明transparent)。
    http://reactnative.cn/docs/0.46/textinput.html#content
    http://www.jianshu.com/p/2f702b52b321

(2) Fetch中的post请求

(1) JSON.parse() :

解析一个JSON字符串,可选地转换生成的值及其属性,并返回值。( 属性:值)( key:value )

换一种说法是:JSON.parse() 方法解析一个JSON字符串,构造由字符串描述的JavaScript值或对象。可以提供可选的reviver函数以在返回之前对所得到的对象执行变换。

(2) JSON.stringify()

返回与指定值相对应的一个JSON字符串,可选地仅包含某些属性或以用户定义的方式替换属性值。

// 将字符串JSON格式化
JSON.parse(responseData)

// 将JSON数据转化为字符串
JSON.stringify(responseData)
 //更新数据源
    this.setState({
      dataSource:this.state.dataSource.cloneWithRows(JSON.parse(responseData).data)
    });

(3) Post请求

执行POST提交,我们可以将method属性值设置为post,并且在body属性值中设置需要提交的数据。

fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    firstParam: 'yourValue',
    secondParam: 'yourOtherValue',
  })
})
-------------------------------------
译注:如果你的服务器无法识别上面POST的数据格式,那么可以尝试传统的form格式,示例如下:
fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: 'key1=value1&key2=value2'
})
-------------------------------------

POST请求实例:

 fetch("http://rapapi.org/mockjs/22101/api/u/signup",{
            method:'POST',
            headers:{
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            body:JSON.stringify( 'phoneNumber': 'phoneNumber1' )
        }).then( (response) =>   response.json()   )
          .then( (data)=> {
            console.log(data.success)
            if(data && data.success){
                _this.showVerifyCode();
            }else{
                alert('发送验证码失败');
            }
        }).catch( (err) => {
            alert('获取验证码失败');
        })

http://www.cnblogs.com/keyi/p/6721710.html
http://www.jianshu.com/p/7c097051b5dc
http://www.51xuediannao.com/javascript/fetchdyf_fetchxydajaxqqfa__1142.html
http://blog.csdn.net/blueheart20/article/details/45174399
https://zhidao.baidu.com/question/7345375.html
iOS9对https的调整,需要在项目的info.plist添加Key:NSAllowsArbitraryLoads,具体方法看http://www.cnblogs.com/shaoting/p/5148323.html

(这里有个巨坑)http://blog.csdn.net/haoranli/article/details/60960858

   {
              this.state.codeSent
               ? 
                      登陆
                      
                :
                  
                        获取验证码
                         
   }
如果不用bind(this)会出现报错

·

(4)验证码倒计时 setInterval() 和 clearInterval()

    
    coutDown() {
        this.setState({
            MainTime:60,
            MainTimeTitle: ''
        });
        this.bb = setInterval( () => {
            var aa = this.state.MainTime - 1;
            if( aa ===0){
                clearInterval( this.bb );
                this.setState({
                    MainTime:'',
                    MainTimeTitle: '重新获取'
                })}else{
                    this.setState({
                        MainTime: aa,
                        MainTimeTitle: ''
                    })
                }
        },1000)
    }
-------------------------------------
 {this.state.MainTime}{this.state.MainTimeTitle}
 

http://www.jianshu.com/p/819259d09609

(踩坑) :这样写的话会有个警告(如下,如图):


React Native学习之路(9) - 注册登录验证的实现 + (用Fetch实现post请求) + (倒计时验证码)+(父子组件通信)+(asyncStorage异步存储) +(TextInput文本输入框)_第1张图片
countDown()中的bb方法一直在执行

(解决方法)如下:

Waring: Can only update a mounted or mounting component. 

分析:可以看到在 countdown方法中每秒中调用一次bb方法去递减秒数,
当组件unmounted之后这个timer并没有停止,所以出现了上面的问题。

--------------------------------------------------------
解决方法:
将每次setInterval返回的ID保存起来,在componentWillUnmount方法中clearInterval
--------------------------------------------------------

完整代码:
    //组件将被卸载
    componentWillUnmount() {
        clearInterval(this.state.timeId)
    }
    //倒计时
    coutDown() {
        this.setState({
            MainTime:60,
            MainTimeTitle: ''
        });
        this.bb = setInterval( () => {
            var aa = this.state.MainTime - 1;
            if( aa ===56 ){
                clearInterval( this.bb );
                this.setState({
                    MainTime:'',
                    MainTimeTitle: '重新获取'
                })}else{
                    this.setState({
                        MainTime: aa,
                        MainTimeTitle: ''
                    })
                }
        },1000)
        this.setState({
            timeId: this.bb
        });
    }

http://blog.csdn.net/tujiaw/article/details/58238975

(5) 提交手机号和验证码

(1) 登陆按钮触发事件:

       {
                        this.state.codeSent
                        ? 
                            登陆
                            
                        :
                         
                                获取验证码
                          
       }

(2) 登陆函数

_submit(){
        var that =  this;
        var loginPhoneNumber = this.state.phoneNumber;
        var loginVerifyCode = this.state.verifyCode;
        // console.log(loginPhoneNumber);
        // console.log(loginVerifyCode);
        if(!loginPhoneNumber || !loginVerifyCode ){
            return alert( 手机号或者验证码错误 );
        }else{
            fetch("http://rapapi.org/mockjs/22101/api/u/verify",{
                method:'POST',
                header: {
                    'Accept':'application/json',
                    'Content-Type':'application/json'
                },
                body: JSON.stringify({
                    'phoneNumber':'loginPhoneNumber',
                    'verifyCode': 'loginVerifyCode'
                })
            }).then( (response) => response.json() )
              .then((data) => {
                if(data && data.success){
                    // console.log(data)
                    // console.log(data.success)
                    // console.log( MOCK.mock(data) )
                    var data = MOCK.mock(data).data;
                    var stringify = JSON.stringify(data);
                    console.log(stringify);
                    // console.log(data.success)    //值是true
                    // that.props.afterLogin(stringify);
                    // console.log(data)
                    that.props.afterLogin(stringify);

                }else{
                    alert('发送验证码失败22222222222');
                }
              })
              .catch( (err) => {
                  alert('获取验证码失败333333333333');
              })
        }
    }

(3) 子组件传值给父组件

  _afterLogin(user) {
        var that = this;
        // user = JSON.stringify(user);
        AsyncStorage.setItem('user',user)
            .then( ()=> {
                console.log( AsyncStorage.getItem(user) )
                that.setState({
                    logined: false,
                    user: user
                })
                console.log(that.state.logined)
            })
        // this.setState(user)
    }


    render(){
        console.log( this.state.logined );   //true

        if(this.state.logined) {
            return ;
        };
        return(
        
        )
    }

这里可以理解为,父组件传递一个方法给子组件,子组件将(值)作为参数返回给父组件,父组件回调
http://blog.csdn.net/hehe0705/article/details/65631768

效果图:


20170724142429.gif

(6) AsyncStorage异步存储

AsyncStorage是一个简单的、异步的、持久化的Key-Value存储系统,它对于App来说是全局性的。它用来代替LocalStorage。

  • AsyncStorage.getItem() :存值


    React Native学习之路(9) - 注册登录验证的实现 + (用Fetch实现post请求) + (倒计时验证码)+(父子组件通信)+(asyncStorage异步存储) +(TextInput文本输入框)_第2张图片
    QQ截图20170724144623.png

你可能感兴趣的:(React Native学习之路(9) - 注册登录验证的实现 + (用Fetch实现post请求) + (倒计时验证码)+(父子组件通信)+(asyncStorage异步存储) +(TextInput文本输入框))