宝宝秀项目学习(四)

// 1、Modal组件的使用
// 2、TextInput组件的使用
// 3、用户登录界面的设计
// 3.1 定时器的使用
// 3.2  小技巧--根据不同的state显示不同的view
// 3.3  子组件给父组件的回调函数
// 3.4  异步存储获取本地资源
//
//
// 一、
// 1、Modal组件:Modal组件可以用来覆盖包含React Native根视图的原生视图(如UIViewController,Activity)。
// 2、TextInput组件:TextInput是一个允许用户在应用中通过键盘输入文本的基本组件。本组件的属性提供了多种特性的配置,譬如自动完成、自动大小写、占位文字,以及多种不同的键盘类型(如纯数字键盘)等等。

<Modal
    animationType={}  //可选属性有'none', 'slide', 'fade
    transparent={}       //是否透明,设置是否为透明的,true或者是false
    visible={}               //设置此modal是否为可见的true或者是false,一般由状态管理器来设置
    onRequestClose={() => { } }   //销毁modal界面时调用,一般就是设置visible的属性为false就行了
    onShow={}                           //模态在显示的时候调用此函数
>
    {/*这里面就是覆盖在上面的内容*/}
    <View style={styles.modalContant}>
        <Icon
            name="ios-close-outline"
            style={styles.backfromModal}
            size={45}
            onPress={this._backfromModal}
        />

        <View style={this.commentBox}>
            <View style={styles.commentNeirong}>
                <TextInput
                    placeholder={'快来评论吧'} //如果没有任何文字输入,会显示此字符串,即提示信息
                    style={styles.pinlun}
                    onFocus={this._focus}    //当文本框获得焦点时调用此方法
                    onBlur={this._blur}      //当文本框失去焦点时调用此方法
                    defaultValue={this.state.content}  //默认值,即可编辑的一开始就在输入框中
                    onChangeText={(text)=>{
                        this.setState({
                            content:text
                        })
                        //使用onChangeText写入state,然后从this.state中取出值。这是唯一的从输入框中取出输入值方法,text就是输入的内容
                    }}
                />
            </View>
        </View>
        <Button
            onPress={this._submit}
            style={styles.submit}
        >
            提交评论
        </Button>
    </View>
</Modal>
// TextInput在安卓上默认有一个底边框,同时会有一些padding。如果要想使其看起来和iOS上尽量一致,则需要设置padding: 0,同时设置underlineColorAndroid="transparent"来去掉底边框。
// 二、用户登录界面
export default class Loginin extends Component {
    constructor(props) {
        super(props)
        this.state={
            phoneNumber:'',               //电话号码
            codeAlreadysSend:false,     //标记是否点击了获取验证码,即是否成功的发送了请求验证码的请求
            verifyCode:'',                //验证码
            seconds:60                      //倒计时
        }
    }
    render() {
        return (
            <View style={styles.container}>
                <View style = {styles.signupBox}>
                    <Text style = {styles.textTitle}> 快速登录</Text>
                    <View style={{height:45}}>
                        <TextInput
                            placeholder={'输入手机号'}
                            autoCapitalize={'none'} //控制TextInput是否要自动将特定字符切换为大写
                            autoCorrect={false}     //如果为false,会关闭拼写自动修正。默认值是true。
                            keyboardType={'phone-pad'}  //决定弹出的何种软键盘的
                            style={styles.inputArea}
                            underlineColorAndroid='transparent' //
                            onChangeText={(text)=>{
                                this.setState({
                                    phoneNumber:text
                                })
                            }}
                        />
                    </View>
                    {this.state.codeAlreadysSend ?    //判断是否已经成功发送了请求验证码的请求
                        <View style={styles.verifyCodeBox}>
                            <TextInput
                                placeholder={'输入验证码'}
                                autoCapitalize={'none'}
                                autoCorrect={false}
                                keyboardType={'phone-pad'}
                                style={styles.inputArea}
                                underlineColorAndroid='transparent'
                                onChangeText={(text)=>{
                                    this.setState({
                                        verifyCode:text
                                    })
                                }}
                            />
                            {this.state.seconds === 0 ?    //判断倒计时是否结束
                                <View style = {styles.countDown}>
                                    <Text style = {styles.countdownText} onPress={this._getVerifyCode}>重新获取</Text>
                                    {/*如果倒计时结束,那么重新获取验证码*/}
                                </View>
                                :
                                <View style = {styles.countDown}>
                                    <Text style = {styles.countdownText}>剩余{this.state.seconds}秒</Text>
                                </View>
                            }
                        </View>
                        : null
                    }
                    {this.state.codeAlreadysSend ?      //根据不同的状态显示不同的View,用三元运算符
                        <View style={styles.sendBtn}>
                            <Text style={styles.btnText} onPress={this._login}>登录</Text>
                        </View>
                        :
                        <View style={styles.sendBtn}>
                            <Text style={styles.btnText} onPress={this._getVerifyCode}>获取验证码</Text>
                        </View>
                    }
                </View>
            </View>
        );
    }
    //点击登录按钮
    _login = ()=> {
        //去服务器验证手机号码与验证码是否匹配
        //正则匹配
        let phoneNumber = this.state.phoneNumber
        let verifyCode = this.state.verifyCode
        if(!phoneNumber || !verifyCode){
            alert('手机号码或验证码不能为空')
            return       //return后将不在执行下面的代码
        }
        let body = {
            phoneNumber:phoneNumber,
            code:verifyCode
        };
        let url = config.apis.base + config.apis.verify
        request.post(url,body)
            .then(
                (data)=>{
                    if(data && data.success){
                        this.props.afterLogin(data.data);  //向父组件回调数据(login是要放在App.js中的,要放到tab的前面)
                    }else{
                        alert('获取验证码失败,请检查您的手机号是否正确')
                    }
                }
            )
            .catch((err)=>{
                alert('错误'+err)
            })
    }
    //点击获取验证码
    _getVerifyCode = ()=> {
        //去服务器获取验证码
        //正则匹配
        let phoneNumber = this.state.phoneNumber
        if(!phoneNumber){
            alert('手机号码不能为空')
            return
        }
        let body = {
            phoneNumber:phoneNumber
        };
        let url = config.apis.base + config.apis.signup
        request.post(url,body)
            .then(
                (data)=>{
                    if(data && data.success){
                        {this._showVerifyCode()}  //请求成功显示输入验证码的输入框和倒计时(都是由状态机控制着)
                    }else{
                        alert('获取验证码失败,请检查您的手机号是否正确')
                    }
                }
            )
            .catch((err)=>{
                alert('错误'+err)
            })
    }
    //显示验证码的输入框和倒计时
    _showVerifyCode=()=>{
        this.setState({
            codeAlreadysSend:true,
            seconds:5
        })
        //开始倒计时,this._setInterval的目的是将setInterval绑定到this,每一秒钟状态机中的seconds要减去一
        this._interval = setInterval(()=>{
            if(this.state.seconds === 0){
                clearInterval(this._interval)
                return
            }
            this.setState({
                seconds:this.state.seconds - 1
            })},1000);
    }
    /**
     * 生命周期方法,组件将被卸载之前
     */
    componentWillUnmount(){
        this._interval && clearInterval(this._interval)   //用计时器必须在组件将被卸载前清除计时操作,不然容易出问题
    }
}


// react-native官网说:我们发现很多React Native应用发生致命错误(闪退)是与计时器有关。具体来说,是在某个组件被卸载(unmount)之后,计时器却仍然在运行。要解决这个问题,只需铭记在unmount组件时清除(clearTimeout/clearInterval)所有用到的定时器即可:
export default class Hello extends Component {
    componentDidMount() {
        this.timer = setTimeout(
            () => { console.log('把一个定时器的引用挂在this上'); },
            500
        );
    }
    componentWillUnmount() {
        // 请注意Un"m"ount的m是小写

        // 如果存在this.timer,则使用clearTimeout清空。
        // 如果你使用多个timer,那么用多个变量,或者用个数组来保存引用,然后逐个clear
        this.timer && clearTimeout(this.timer);
    }
};

// 在App.js中,已进入render函数,首先判断本地存储中是否有用户信息
if(!this.state.logined){   //这里每执行一次render函数都会重新判断一次logined。
    return(
        <Login afterLogin={this._afterLogin}/>     //用户登录页面,放在tab组件的外面
    )
}
// 用户第一次打开App的时候,登录成功后会将用户信息持久化到本地

//用户登录成功的回调函数(这里是子组件登陆成功,给父组件的回调)
_afterLogin = (user) => {
    //    user是一个用户信息对象
    let user2 =JSON.stringify(user);
    AsyncStorage.setItem('user',user2)      //异步存储用户信息到本地
        .then(     //then()函数是上一步成功后执行
            ()=>{
                this.setState({
                    logined:true,   //注意:state每改变一次,就重新渲染一次(即重新执行一次render函数),
                    user:user2                                            // 所以登陆成功后的页面跳转是不需要Navigator的。
                })
            }
        )
        .catch((err)=>{
            alert('存储发生错误'+err)
        })



    //异步获取用户登录状态和信息
    _asyncGetAppStatus = ()=> {
        AsyncStorage.getItem('user')
            .then(
                (data)=>{
                    let user;
                    let newState = {};   //定义一个空对象
                    if(data){
                        user = JSON.parse(data);  //JSON.parse()方法用来解析json字符串成JavaScript对象
                    }
                    if(user && user.accesssToken){
                        newState.logined = true;
                        newState.user = user;
                        //就相当于 newState = {logined:true,user:user}
                    }else{
                        newState.loaded = false;
                    }
                    this.setState(newState);
                }
            )
            .catch((err) =>{
                alert('AsyncStorage err'+err)
            })
    }   }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值