React Native 系列(五) -- 組件間傳值

前言

本系列是基於React Native版本號0.44.3寫的。任何一款 App 都有界面之間數據傳遞的這個步驟的,那麼在RN中,組件間是怎麼傳值的呢?這篇文章將介紹到順傳、逆傳已經經過通知傳值。flex

順傳

其實咱們在本系列第二篇文章中,講述PropsState的時候就已經接觸了順傳。this

  • 經過props傳值code

    舉個🌰:父控件給子控件傳遞一個name屬性的值,子控件展現父控件傳遞過來的值:component

    // 子組件
    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拿到組件,而後傳值rem

    舉個🌰:經過點擊屏幕上的 + 號按鈕,實現沒點擊一次,讓SonComponent的輸出數字加1。it

    // 子組件
    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',
        },
    });

逆傳

  • 使用方法回調:class

    1. 在父組件定義一個處理接收值的方法
    2. 把這個方法傳遞給子組件,而且綁定this,子組件就能經過this.props拿到這個方法調用

舉個例子,一樣是點擊屏幕上的 + ,讓屏幕上的數字 加 1。(ps:和上面經過ref拿到子組件,傳遞的代碼有區別,注意組件層級)List

// 子組件
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',
    },
});

點擊發送生活費,就能夠看到弟弟能接收到生活費。

好了,組件間傳值就講到這裏了。

致謝

若是發現有錯誤的地方,歡迎各位指出,謝謝!

相關文章
相關標籤/搜索