React Native 组件间传值

1

前言

本系列是基于React Native版本号0.44.3写的。任何一款 App 都有界面之间数据传递的这个步骤的,那么在RN中,组件间是怎么传值的呢?这篇文章将介绍到顺传、逆传已经通过通知传值。

  • 顺传

其实我们在本系列第二篇文章中,讲述Props和State的时候就已经接触了顺传。

通过props传值

举个例子:父控件给子控件传递一个name属性的值,子控件展示父控件传递过来的值:

// 子组件
class SonComponent extends Component {
    render(){
        return (
            <View style={styles.sonViewStyle}>
                <Text style={{fontSize: 20}}>这是父视图传递过来的数据:{this.props.name}</Text>
            </View>
        );
    }
}

// 父组件
class FatherComponent extends Component {
    render(){
        return (
            <View style={styles.container}>
                <SonComponent name={this.props.name}/>
            </View>
        );
    }
}

// 主组件
export default class RNDemoOne extends Component {
    render() {
        return (
            <View style={styles.container}>
                <FatherComponent name="scott"/>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: 'red',
    },

    sonViewStyle: {
        flex: 1,
        backgroundColor: '#F5FCFF',
        justifyContent: 'center',
        alignItems: 'center',
    },
});

上述代码的数据传递其实是这样的: 主组件 -> FatherComponent -> SonComponent。
但是有时候,我们并不是在创建 子组件 的时候就传递值,而是需要等待某个触发事件的时候,再传递,这就涉及到获取子组件传值。

  • 通过ref拿到组件,然后传值

举个🌰:通过点击屏幕上的 + 号按钮,实现没点击一次,让SonComponent的输出数字加1。

// 子组件
class SonComponent extends Component {

    // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.state = {
            number: 1
        };
    }

    addClick(number){
        this.setState({
            number: number
        });
    }

    render(){
        return (
            <View style={styles.sonViewStyle}>
                <Text style={{fontSize: 20}}>{this.state.number}</Text>
            </View>
        );
    }
}

// 父组件
class FatherComponent extends Component {
    render(){
        return (
            <View style={styles.container}>
                <SonComponent ref="son" number={this.props.number}/>

                <View style={styles.fatherViewStyle}>
                    <Text style={{fontSize: 40}} onPress={() => {
                                                                this.refs.son.addClick(this.refs.son.state.number + 1)
                }}>{"+"}</Text>
                </View>
            </View>
        );
    }
}

// 主组件
export default class RNDemoOne extends Component {
    render() {
        return (
            <View style={styles.container}>
                <FatherComponent number={1}/>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },

    sonViewStyle: {
        flex: 1,
        backgroundColor: '#F5FCFF',
        justifyContent: 'center',
        alignItems: 'center',
    },

    fatherViewStyle: {
        flex: 1,
        justifyContent: 'center',
        alignItems:'center',
    },
});

逆传

使用方法回调:

在父组件定义一个处理接收值的方法
把这个方法传递给子组件,并且绑定this,子组件就能通过this.props拿到这个方法调用
举个例子,同样是点击屏幕上的 + ,让屏幕上的数字 加 1。(ps:和上面通过ref拿到子组件,传递的代码有区别,注意组件层级)

// 子组件
class SonComponent extends Component {
    addClick(){
        this.props.receiveNumber()
    }

    render(){
        return (
            <View style={styles.sonViewStyle}>
                    <Text style={{fontSize: 40}} onPress={this.addClick.bind(this)}>{"+"}</Text>
            </View>
        );
    }
}

// 父组件
class FatherComponent extends Component {

    // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.state = {
            number: 1
        };
    }

    receiveNumber(){
        var m = this.state.number;
        m += 1;
        this.setState({
            number: m
        });
    }

    render(){
        return (
            <View style={styles.container}>
                <SonComponent receiveNumber={this.receiveNumber.bind(this)}/>

                <View style={styles.fatherViewStyle}>
                    <Text style={{fontSize: 20}}>{this.state.number}</Text>
                </View>
            </View>
        );
    }
}

// 主组件
export default class RNDemoOne extends Component {
  render() {
    return (
        <View style={styles.container}>
            <FatherComponent/>
        </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
      flex: 1,
  },

    sonViewStyle: {
        flex: 1,
        backgroundColor: '#F5FCFF',
        justifyContent: 'center',
        alignItems: 'center',
    },

    fatherViewStyle: {
        flex: 1,
        justifyContent: 'center',
        alignItems:'center',
    },
});

通知

当两个组件之间互相拿不到谁的时候,可以用通知传值。比如当两个组件是同一层级关系的时候(兄弟关系)。
举个例子: 点击发送生活费,哥哥就给弟弟发送100生活费。

// 弟弟组件
class DiDiComponent extends Component {

    // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.state = {
            money: 0
        };
    }

    componentDidMount() {
        // 添加监听者
        this.listener = DeviceEventEmitter.addListener('makeMoney', (money) => {
            this.setState({
                money: money
            });
        })
    }

    componentWillUnmount() {
        // 销毁监听者
        this.listener.remove();
    }

    render(){
        return (
            <View style={styles.didiStyle}>
                <Text>弟弟</Text>
                <Text>收到{this.state.money}零花钱</Text>
            </View>
        );
    }
}

// 哥哥组件
class GeGeComponent extends Component {

    render(){
        return (
            <View style={styles.gegeStyle}>
                <Text>哥哥</Text>
                <Text onPress={()=>{
                    DeviceEventEmitter.emit('makeMoney', 100)
                }}>发生活费</Text>
            </View>
        );
    }
}

// 主组件
export default class RNDemoOne extends Component {
  render() {
    return (
        <View style={styles.container}>
            <DiDiComponent/>
            <GeGeComponent/>
        </View>
    );
  }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },

    didiStyle: {
        flex: 1,
        backgroundColor: '#F5FCFF',
        justifyContent: 'center',
        alignItems: 'center',
    },

    gegeStyle: {
        flex: 1,
        justifyContent: 'center',
        alignItems:'center',
    },
});

点击发送生活费,就可以看到弟弟能接收到生活费。


如果觉得我的文章对你有用,请随意赞赏

你可能感兴趣的

载入中...