react-native入门(五)----状态机和父子组件传值以及属性props

1,606 阅读5分钟

由于他们三者实际使用中可能会有或多或少的联系,为了便于理解和后续的使用,这里先拥挤一下,写到一起,方便查看,这里分解介绍 状态机state、父子组件、props

状态机state

顾名思义状态机就是保存状态的装置,在RN里面,其实就是state,我们可以通过设置state和改变state里面的值来设置和调整UI元素的变动,对于不需要变动的UI写死即可

举个例子:

1.初始化UI

//构造方法 constructor里面设置初始state
this.state= {
    name: '充电宝',
    gender: '未知'
}
//render里面设置UI
<View>
    <Text>{this.state.name}</Text>
    {
        this.state.gender !== '未知'
        &&
        <Text>{this.state.gender}</Text>
    }
</View>

以上代码设置完毕后,会发现界面上只显示了一个充电宝,正常显示

下面的gener是在gender不为未知的情况下显示的,可以通过其条件性的控制UI的显隐,注意:{} 必须要有

2.更新UI

如果我们在网络请求完毕后,需要更新UI怎么办呢,以上为例

一般是在componentDidMout方法里面进行网络请求,这里界面初次初始化渲染成功,比较适合网络请求,此时网络请求完成值后只需要调用setState方法即可更新UI了,例如:

    let result = request.fetch(params)
    let name = result.name
    let gender = result.gender
    let age = result.age
    this.setState({
        name,
        gender: gender,
        age
    })
    //设置完成之后,name和gender就会根据最新值更新了,age由于UI的xml上没有用到,实际不会渲染的

通过setState方法设置成功后的变量其实就是,this.state = {} 里面的对象,当执行完毕setState方法之后,便会对新设置的值和以前UI树上面的值进行对比,如果不一样系统会自动更新替换xml树上的变量保存的内容,没有的状态值也不会影响渲染(但是会占用状态机控件,对比渲染时,影响渲染效率,性能优化时尽量避免此情况)

在上面可以看到设置state的时候,有的是直接写了一个键值就可以了,有的写上键值对的形式,其实,只要你上面声明的变量名和需要渲染的变量的键值一样,那么可以使用键值代替键值对

扩展: 学习了props可以尝试一下,在子视图或者别的视图中能不能通过父视图的引用设置父视图的state吧,相信掌握了会对以后的进阶有帮助的

父子组件和props

顾名思义,就是父组件和子组件,父组件在下,子组件在上,通过flexbox布局以及合理的使用他们的关系可以布局出各种各样的UI出来,在flexbox布局里面相信已经了解到他们之间是怎么结合布局的

这里介绍父子组件的传值,正常我们想的父子组件看到的view可能是这个样子的(这样传值好像没必要哈)

 <View>
    <View type={1}></View>
 </View>

实际可能是这个样子,实际传值的内容可能是根据当前控制器(也是他的父视图),来传值的

<View>
    <ChildView type={this.data.type}>
    <ChileView>
</View>
//这样一个叫做type的属性就会传入到子视图当中去了,而子视图当中怎么接收呢,这就涉及到props了

props即属性,this.props自己的属性集合,父视图传过来的参数(属性),会存到子视图props里

子视图中可以通过this.props可以获取子视图自己的属性列表,如果传入了type,那么调用的时候可以通过这样获取,父视图也同理可以同样的方式获取到自己的

let type = this.props.type
const {type, name, gender} = this.props  //一次获取多个属性变量

是不是很简单这样就可以传值了,那么子组件如果回调结果给父组件呢,方法如下

1.父视图设置一个回调(接口或者函数),子视图在合适的时机调用(推荐)

//fatherView
//render
render() {
    return (
        <ChildView onSubmit={()=>{
            //父视图设置的回调方法,快捷方法   
        }}> </ChildView>
    
        //当然有洁癖也可以也可以这样
        <ChildView onSubmit={()=>this.submit()}> </ChildView> //推荐写法,避免错误
        <ChildView onSubmit={this.submit.bind(this)}> </ChildView> //也可以这么调用
    )
}
//如果view的回调声明onSubmit那里没有()=>或者调用bind(this),这里必须这么声明,一个好习惯,不然调用不到这个方法
submit = () => {
}
submit () {
}

//子视图
//render
render() {
    return (
        <TouchableOpacity
            onPress={()=>{
                this.props.onSubmit && this.props.onSubmit()  //先判断一下是否存在在调用  
            }}>
        </TouchableOpacity>
    )
}

2.由于对象里面的方法均为public,那么可以通过传递父视图的引用,在子视图调用传值

//fatherView
//render
render() {
    return (
        //当然有洁癖也可以也可以这样
        <ChildView superView={this}> </ChildView>
    )
}
//如果view的回调声明onSubmit那里没有()=>或者调用bind(this),这里必须这么声明,一个好习惯,不然调用不到这个方法
submit = () => {

}

//子视图
//render
render() {
    return (
        <TouchableOpacity
            onPress={()=>{
                this.superView && this.superView.submit && this.superView.submit()  //先判断一下是否存在在调用  
            }}>
        </TouchableOpacity>
    )
}

上面就是比较简单易用的父子组件传值了,以props为媒介来完成

上面子视图中通过传递父视图引用,是不是发现也可以拿到父视图的props和更新state了呢,由于方法都是public,试试去看看能不能拿到并且操作吧

属性声明

子控件prop如果未声明,正常写外面可能没有代码提示,正常该怎么声明让外界调用更方便呢

附上实例代码:

    //默认属性,外面没实现里面使用这个(这个类似于类方法)
    static defaultProps={
        onUpdate: f => f //意思是什么也不执行,回调
        title: '123'
    }
    //外面实现了里面会发生改变
    static propTypes={
        onUpdate: f => f //意思是什么也不执行,回调
        title: text
    }
}

父子组件渲染流程:

父组件:componentWillMount->render->componentDidMount

父子组件:componentWillMount(父)->componentWillMount(子)->render->componentDidMount(子)->componentDidMount(父)

又粘出来了,可以自己测试一下他们的顺序哈