跳至主要内容
版本: 6.x

导航事件

您可以监听 React Navigation 发出的各种事件,以在某些事件发生时收到通知,并在某些情况下覆盖默认操作。 有一些核心事件,例如 focusblur 等(在下面有记录),适用于每个导航器,以及仅适用于某些导航器的导航器特定事件。

除了核心事件之外,每个导航器都可以发出自己的自定义事件。 例如,堆栈导航器发出 transitionStarttransitionEnd 事件,选项卡导航器发出 tabPress 事件等。 您可以在各个导航器的文档中找到有关发出的事件的详细信息。

核心事件

以下是每个导航器中可用的事件

focus

当屏幕进入焦点时,会发出此事件。

在大多数情况下,useFocusEffect 钩子可能比手动添加监听器更合适。 有关如何决定应该使用哪个 API 的更多详细信息,请参阅 本指南

blur

当屏幕失去焦点时,会触发此事件。

state

当导航器状态发生变化时,会触发此事件。此事件会在事件数据中接收导航器状态 (event.data.state)。

beforeRemove

当用户离开屏幕时,会触发此事件,有机会 阻止用户离开

监听事件

有多种方法可以监听导航器发出的事件。每个注册为事件监听器的回调函数都会接收一个事件对象作为参数。事件对象包含一些属性

  • data - 导航器传递的有关事件的附加数据。如果未传递数据,则可能为 undefined
  • target - 应接收事件的屏幕的路由键。对于某些事件,如果事件与特定屏幕无关,则可能为 undefined
  • preventDefault - 对于某些事件,事件对象上可能存在 preventDefault 方法。调用此方法将阻止事件执行的默认操作(例如,在 tabPress 上切换选项卡)。仅对某些事件(如 tabPress)提供阻止操作的支持,并非所有事件都支持。

您可以使用以下 API 监听事件

在屏幕内,您可以使用 addListener 方法在 navigation 属性上添加监听器。addListener 方法接受 2 个参数:事件类型和在事件发生时要调用的回调函数。它返回一个可以被调用的函数,用于取消订阅事件。

示例

const unsubscribe = navigation.addListener('tabPress', (e) => {
// Prevent default action
e.preventDefault();
});

通常,您会在 React.useEffect 中为函数组件添加事件监听器。例如

function Profile({ navigation }) {
React.useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
// do something
});

return unsubscribe;
}, [navigation]);

return <ProfileContent />;
}

unsubscribe 函数可以作为效果中的清理函数返回。

对于类组件,您可以在 componentDidMount 生命周期方法中添加事件,并在 componentWillUnmount 中取消订阅

class Profile extends React.Component {
componentDidMount() {
this._unsubscribe = navigation.addListener('focus', () => {
// do something
});
}

componentWillUnmount() {
this._unsubscribe();
}

render() {
// Content of the component
}
}

需要注意的是,您只能使用 addListener 监听来自当前导航器的事件。例如,如果您尝试在嵌套在标签内的堆栈中的屏幕中添加监听器,它将不会收到 tabPress 事件。如果您需要监听来自父导航器的事件,可以使用 navigation.getParent 获取对父导航器导航属性的引用并添加监听器。

const unsubscribe = navigation
.getParent('MyTabs')
.addListener('tabPress', (e) => {
// Do something
});

这里 'MyTabs' 指的是您在要监听其事件的父 Tab.Navigatorid 属性中传递的值。

Screen 上的 listeners 属性

有时您可能希望从定义导航器的组件而不是屏幕内部添加监听器。您可以使用 Screen 组件上的 listeners 属性添加监听器。listeners 属性接受一个对象,该对象以事件名称为键,以监听器回调为值。

示例

<Tab.Screen
name="Chat"
component={Chat}
listeners={{
tabPress: (e) => {
// Prevent default action
e.preventDefault();
},
}}
/>

您还可以传递一个回调函数,该函数返回包含监听器的对象。它将接收 navigationroute 作为参数。

示例

<Tab.Screen
name="Chat"
component={Chat}
listeners={({ navigation, route }) => ({
tabPress: (e) => {
// Prevent default action
e.preventDefault();

// Do something with the `navigation` object
navigation.navigate('AnotherPlace');
},
})}
/>

导航器上的 screenListeners 属性

您可以将名为 screenListeners 的属性传递给导航器组件,您可以在其中指定对该导航器所有屏幕事件的监听器。如果您想监听特定事件(无论屏幕如何),或者想监听诸如 state 之类的公共事件(它会向所有屏幕发出),这将很有用。

示例

<Stack.Navigator
screenListeners={{
state: (e) => {
// Do something with the state
console.log('state changed', e.data);
},
}}
>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>

listeners 类似,您也可以将函数传递给 screenListeners。该函数将接收每个屏幕的 navigation 属性route 属性。如果您需要访问 navigation 对象,这将很有用。

<Tab.Navigator
screenListeners={({ navigation }) => ({
state: (e) => {
// Do something with the state
console.log('state changed', e.data);

// Do something with the `navigation` object
if (!navigation.canGoBack()) {
console.log("we're on the initial screen");
}
},
})}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>