导航事件
您可以监听 React Navigation 发出的各种事件,以在某些事件发生时收到通知,并在某些情况下覆盖默认操作。 有一些核心事件,例如 focus
、blur
等(在下面有记录),适用于每个导航器,以及仅适用于某些导航器的导航器特定事件。
除了核心事件之外,每个导航器都可以发出自己的自定义事件。 例如,堆栈导航器发出 transitionStart
和 transitionEnd
事件,选项卡导航器发出 tabPress
事件等。 您可以在各个导航器的文档中找到有关发出的事件的详细信息。
核心事件
以下是每个导航器中可用的事件
focus
当屏幕进入焦点时,会发出此事件。
在大多数情况下,useFocusEffect
钩子可能比手动添加监听器更合适。 有关如何决定应该使用哪个 API 的更多详细信息,请参阅 本指南。
blur
当屏幕失去焦点时,会触发此事件。
state
当导航器状态发生变化时,会触发此事件。此事件会在事件数据中接收导航器状态 (event.data.state
)。
beforeRemove
当用户离开屏幕时,会触发此事件,有机会 阻止用户离开。
监听事件
有多种方法可以监听导航器发出的事件。每个注册为事件监听器的回调函数都会接收一个事件对象作为参数。事件对象包含一些属性
data
- 导航器传递的有关事件的附加数据。如果未传递数据,则可能为undefined
。target
- 应接收事件的屏幕的路由键。对于某些事件,如果事件与特定屏幕无关,则可能为undefined
。preventDefault
- 对于某些事件,事件对象上可能存在preventDefault
方法。调用此方法将阻止事件执行的默认操作(例如,在tabPress
上切换选项卡)。仅对某些事件(如tabPress
)提供阻止操作的支持,并非所有事件都支持。
您可以使用以下 API 监听事件
navigation.addListener
在屏幕内,您可以使用 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.Navigator
的 id
属性中传递的值。
Screen
上的 listeners
属性
有时您可能希望从定义导航器的组件而不是屏幕内部添加监听器。您可以使用 Screen
组件上的 listeners
属性添加监听器。listeners
属性接受一个对象,该对象以事件名称为键,以监听器回调为值。
示例
<Tab.Screen
name="Chat"
component={Chat}
listeners={{
tabPress: (e) => {
// Prevent default action
e.preventDefault();
},
}}
/>
您还可以传递一个回调函数,该函数返回包含监听器的对象。它将接收 navigation
和 route
作为参数。
示例
<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>