天天看點

React Native之didFocus和didBlur

1  didFocus和didBlur解釋

didFocus - the screen focused (if there was a transition, the transition completed)
 
didBlur - the screen unfocused (if there was a transition, the transition completed)      

didFocus是指目前頁面第一次加載的時候會調用一次

didBlur是指目前頁面離開的時候會調用一次(前提是目前頁面沒有被銷毀既沒有執行componentWillUnmount()函數)

2 測試代碼

import React from 'react';
import { View, Text, Button} from 'react-native';
import { createStackNavigator } from 'react-navigation';
 
 
class HomeScreen extends React.Component {
 
 
   constructor(props) {
    super(props);
    console.log("HomeScreen constructor start");
        this.didFocusListener = this.props.navigation.addListener(
        'didFocus',
        (obj) => {console.log("HomeScreen didFocus start")}
        );
    this.didBlurListener = this.props.navigation.addListener(
        'didBlur',
        (obj) => {console.log('HomeScreen didBlur start')}
        );
    }
 
    static navigationOptions = {
        title : 'HomeScreen',
    }
 
    componentDidMount = () => {
                console.log("HomeScreen componentDidMount start")
    }
 
    componentWillUnmount() {
        console.log("HomeScreen componentWillUnmount start")
        this.didFocusListener.remove();
        this.didBlurListener.remove();
    }
 
    render() {
        return (
            <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
               <Text>Home Screen</Text>
 
               <Button onPress={() => this.props.navigation.navigate('Details', {
                   itemId:100,
                   otherParam:'chenyu',
               })} title = "go to Details"/>
  
               <Button
            title="Go back"
            onPress={() => this.props.navigation.goBack()}
              />
        </View>
    );
 
    }
}
 
class DetailsScreen extends React.Component {
 
 
   constructor(props) {
    super(props);
    console.log("DetailsScreen constructor start");
        this.didFocusListener = this.props.navigation.addListener(
        'didFocus',
        (obj) => {console.log("DetailsScreen didFocus start")}
    );
    this.didBlurListener = this.props.navigation.addListener(
        'didBlur',
        (obj) => {console.log('DetailsScreen didBlur start')}
    );
    }
 
 
    static navigationOptions = ({navigation}) => {
        return {
            title : navigation.getParam('otherParam', 'no-values'),
        };
    };
    componentDidMount = () => {
        console.log("DetailsScreen componentDidMount start")
    }
 
    componentWillUnmount() {
    console.log("DetailsScreen componentWillUnmount start")
        this.didFocusListener.remove();
    this.didBlurListener.remove();
    }
 
    render() {
        const {navigation} = this.props;
        const itemId = navigation.getParam('itemId', 'no-values');
        const otherParam = navigation.getParam('otherParam', 'no-values');
 
        return (
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
            <Text>Details Screen</Text>
        <Text>itemId:{JSON.stringify(itemId)}</Text>
        <Text>otherParam:{JSON.stringify(otherParam)}</Text>
        <Button
            title="Go to Details... again"
            onPress={() => this.props.navigation.push('Details', {
                itemId: Math.floor(Math.random() * 100),
        })}
        />
        <Button
            title="Go to Home"
            onPress={() => this.props.navigation.navigate('Home')}
        /> 
        <Button
            title="Go back"
            onPress={() => this.props.navigation.goBack()}
        />
        <Button
            title="Go popToTop"
            onPress={() => this.props.navigation.popToTop()}
        />
           </View>
       );
    }
}
 
 
const RootStack = createStackNavigator(
    {
        Home: HomeScreen,
        Details: DetailsScreen,
    },
    {
        initialRouteName: 'Home',
    }
);
 
 
export default class App extends React.Component {
 
    constructor(props) {
    super(props);
    }
    render() {
        return <RootStack/>;
    }
 
 
}
       

3 運作結果

2個頁面分别如下

React Native之didFocus和didBlur
React Native之didFocus和didBlur

在控制台過來

React

Native指令

adb logcat | grep ReactNativeJS      

1) 程式起來列印日志如下

I/ReactNativeJS(21233): HomeScreen constructor start
I/ReactNativeJS(21233): HomeScreen componentDidMount start
I/ReactNativeJS(21233): HomeScreen didFocus start      

這裡的didFocus start是在componentDidMount後面執行

2 ) 然後點選go to DETAILS按鈕日志如下

I/ReactNativeJS(21233): DetailsScreen constructor start
I/ReactNativeJS(21233): DetailsScreen componentDidMount start
I/ReactNativeJS(21233): HomeScreen didBlur start
I/ReactNativeJS(21233): DetailsScreen didFocus start      

然後執行了HomeScreen didBlur start,但是并沒有執行HomeScreen componentWillUnmount start,因為頁面還沒有銷毀,是以執行了HomeScreen didBlur start.

3 )然後在在第二個頁面點選"GO BACK"或者按下傳回鍵,日志列印如下

I/ReactNativeJS(21233): DetailsScreen componentWillUnmount start
I/ReactNativeJS(21233): HomeScreen didFocus start      

發現沒有,既然執行了componentWillUnmount函數,說明頁面已經銷毀,既然銷毀了,就沒有執行DetailsScreen didBlur start,因為前面的頁面沒有死,是以不會重新加載再次調用首頁的constructor和componentDidMount方法.從前面日志列印

I/ReactNativeJS(21233): DetailsScreen constructor start
I/ReactNativeJS(21233): DetailsScreen componentDidMount start
I/ReactNativeJS(21233): HomeScreen didBlur start
I/ReactNativeJS(21233): DetailsScreen didFocus start      

可以看出,另外一個頁面執行新頁面的constructor函數和componentDidMount函數才執行之前頁面的didBlur start,是以估計這裡是來不及執行頁面就銷毀了,是以沒有列印DetailsScreen didBlur start.

4 )然後再次點選傳回實體鍵日志如下

I/ReactNativeJS(23183): HomeScreen componentWillUnmount start

隻調用了componentWillUnmount函數,是以頁面銷毀了,HomeScreen didBlur start來不及列印.

4 總結

didFocus隻會在目前頁面的constructor函數和componentDidMount函數後面執行

didBlur隻會在目前頁面沒有調用componentWillUnmount函數,然後離開目前頁面才執行,也意味着,這個頁面沒有死但是去了另外一個頁面才會調用,如果自己頁面死了,就不會調用到這裡.