常见操作参考
导航操作是至少包含 type
属性的对象。在内部,该操作可以由 routers 使用 getStateForAction
方法处理,以从现有 导航状态 返回新状态。
¥A navigation action is an object containing at least a type
property. Internally, the action can be handled by routers with the getStateForAction
method to return a new state from an existing navigation state.
每个导航操作至少可以包含以下属性:
¥Each navigation actions can contain at least the following properties:
-
type
(必需的) - 表示操作名称的字符串。¥
type
(required) - A string that represents the name of the action. -
payload
(选项) - 包含有关操作的附加信息的对象。例如,对于navigate
,它将包含name
和params
。¥
payload
(options) - An object containing additional information about the action. For example, it will containname
andparams
fornavigate
. -
source
(可选) - 应被视为操作源的路由的键。这用于某些操作以确定要应用该操作的路由。默认情况下,navigation.dispatch
添加调度操作的路由的键。¥
source
(optional) - The key of the route which should be considered as the source of the action. This is used for some actions to determine which route to apply the action on. By default,navigation.dispatch
adds the key of the route that dispatched the action. -
target
(可选) - 应应用操作的 导航状态 的键。¥
target
(optional) - The key of the navigation state the action should be applied on.
需要强调的是,当操作未处理时,分派导航操作不会引发任何错误(类似于当你分派未由 redux 中的 reducer 处理的操作并且什么也没有发生时)。
¥It's important to highlight that dispatching a navigation action doesn't throw any error when the action is unhandled (similar to when you dispatch an action that isn't handled by a reducer in redux and nothing happens).
常见动作
¥Common actions
该库在 CommonActions
命名空间下导出多个动作创建器。你应该使用这些操作创建器,而不是手动编写操作对象。
¥The library exports several action creators under the CommonActions
namespace. You should use these action creators instead of writing action objects manually.
navigate
navigate
操作允许导航到特定路由。它需要以下参数:
¥The navigate
action allows to navigate to a specific route. It takes the following arguments:
-
name
- string - 当前或父导航器中屏幕的目标名称。¥
name
- string - A destination name of the screen in the current or a parent navigator. -
params
- object - 用于目标路由的参数。¥
params
- object - Params to use for the destination route.
- Static
- Dynamic
navigation.dispatch(
CommonActions.navigate('Profile', { user: 'jane' })
);
navigation.dispatch(
CommonActions.navigate('Profile', { user: 'jane' })
);
在堆栈导航器(stack 或 原生堆栈)中,使用屏幕名称调用 navigate
将具有以下行为:
¥In a stack navigator (stack or native stack), calling navigate
with a screen name will have the following behavior:
-
如果你已经在同名的屏幕上,它将更新其参数并且不会推送新屏幕。
¥If you're already on a screen with the same name, it will update its params and not push a new screen.
-
如果你在不同的屏幕上,它将把新屏幕推送到堆栈上。
¥If you're on a different screen, it will push the new screen onto the stack.
-
如果指定了
getId
属性,并且堆栈中的另一个屏幕具有相同的 ID,它将导航到该屏幕并更新其参数。¥If the
getId
prop is specified, and another screen in the stack has the same ID, it will navigate to that screen and update its params instead.
navigate
操作还可以接受具有以下属性的对象作为参数:
¥The navigate
action can also accepts an object as the argument with the following properties:
-
name
- string - 当前或父导航器中屏幕的目标名称¥
name
- string - A destination name of the screen in the current or a parent navigator -
params
- object - 用于目标路由的参数。¥
params
- object - Params to use for the destination route. -
merge
- boolean - 我们是否应该将当前路由的参数与提供的params
合并。默认为false
。¥
merge
- boolean - Whether we should merge the params of the current route with the providedparams
. Defaults tofalse
. -
path
- string - 与屏幕关联的路径(来自深层链接或通用链接)。¥
path
- string - The path (from deep link or universal link) to associate with the screen.
reset
reset
操作允许将 导航状态 重置为给定状态。它需要以下参数:
¥The reset
action allows to reset the navigation state to the given state. It takes the following arguments:
-
state
- object - 要使用的新 导航状态 对象。¥
state
- object - The new navigation state object to use.
- Static
- Dynamic
navigation.dispatch(
CommonActions.reset({
index: 1,
routes: [
{
name: 'Profile',
params: { user: 'jane', key: route.params.key },
},
{ name: 'Home' },
],
})
);
navigation.dispatch(
CommonActions.reset({
index: 1,
routes: [
{
name: 'Profile',
params: { user: 'jane', key: route.params.key },
},
{ name: 'Home' },
],
})
);
reset
中指定的状态对象用新的状态对象替换现有的 导航状态。这意味着,如果你提供不带键的新路由对象,或使用不同键的路由对象,它将删除这些路由的现有屏幕并添加新屏幕。
¥The state object specified in reset
replaces the existing navigation state with the new one. This means that if you provide new route objects without a key, or route objects with a different key, it'll remove the existing screens for those routes and add new screens.
如果你想保留现有屏幕但只想修改状态,你可以将一个函数传递给 dispatch
,你可以在其中获取现有状态。然后你可以根据需要更改它(确保不要改变现有状态,而是为你的更改创建新的状态对象)。并返回具有所需状态的 reset
操作:
¥If you want to preserve the existing screens but only want to modify the state, you can pass a function to dispatch
where you can get the existing state. Then you can change it as you like (make sure not to mutate the existing state, but create new state object for your changes). and return a reset
action with the desired state:
import { CommonActions } from '@react-navigation/native';
navigation.dispatch((state) => {
// Remove all the screens after `Profile`
const index = state.routes.findIndex((r) => r.name === 'Profile');
const routes = state.routes.slice(0, index + 1);
return CommonActions.reset({
...state,
routes,
index: routes.length - 1,
});
});
将导航器的状态对象视为内部对象,并且可能会在次要版本中发生更改。避免使用除 index
和 routes
之外的 导航状态 状态对象的属性,除非你确实需要它。如果某些功能在不依赖状态对象的结构的情况下无法实现,请提出问题。
¥Consider the navigator's state object to be internal and subject to change in a minor release. Avoid using properties from the navigation state state object except index
and routes
, unless you really need it. If there is some functionality you cannot achieve without relying on the structure of the state object, please open an issue.
用 reset
改写历史
¥Rewriting the history with reset
由于 reset
操作可以使用新的状态对象更新导航状态,因此它可以用于重写导航历史记录。但是,在大多数情况下,不建议重写历史记录来更改返回堆栈:
¥Since the reset
action can update the navigation state with a new state object, it can be used to rewrite the navigation history. However, rewriting the history to alter the back stack is not recommended in most cases:
-
它可能会导致令人困惑的用户体验,因为用户希望能够返回到之前所在的屏幕。
¥It can lead to a confusing user experience, as users expect to be able to go back to the screen they were on before.
-
当支持 Web 平台时,浏览器的历史记录仍然会反映旧的导航状态,因此如果用户使用浏览器的后退按钮,他们将看到旧的屏幕 - 根据用户按下的后退按钮,会产生两种不同的体验。
¥When supporting the Web platform, the browser's history will still reflect the old navigation state, so users will see the old screen if they use the browser's back button - resulting in 2 different experiences depending on which back button the user presses.
因此,如果你有这样的用例,请考虑采用不同的方法 - 例如一旦用户导航回已更改的屏幕,就会更新历史记录。
¥So if you have such a use case, consider a different approach - e.g. updating the history once the user navigates back to the screen that has changed.
goBack
goBack
动作创建器允许返回到历史上的上一条路由。它不需要任何争论。
¥The goBack
action creator allows to go back to the previous route in history. It doesn't take any arguments.
- Static
- Dynamic
navigation.dispatch(CommonActions.goBack());
navigation.dispatch(CommonActions.goBack());
如果你想从特定路由返回,你可以添加一个引用路由键的 source
属性和一个引用包含该路由的导航器的 key
的 target
属性:
¥If you want to go back from a particular route, you can add a source
property referring to the route key and a target
property referring to the key
of the navigator which contains the route:
- Static
- Dynamic
navigation.dispatch({
...CommonActions.goBack(),
source: route.key,
target: route?.params?.key,
});
navigation.dispatch({
...CommonActions.goBack(),
source: route.key,
target: route?.params?.key,
});
默认情况下,分派操作的路由的键作为 source
属性传递,target
属性为 undefined
。
¥By default, the key of the route that dispatched the action is passed as the source
property and the target
property is undefined
.
preload
preload
操作允许在导航到屏幕之前在后台预加载该屏幕。它需要以下参数:
¥The preload
action allows preloading a screen in the background before navigating to it. It takes the following arguments:
-
name
- string - 当前或父导航器中屏幕的目标名称。¥
name
- string - A destination name of the screen in the current or a parent navigator. -
params
- object - 用于目标路由的参数。¥
params
- object - Params to use for the destination route.
- Static
- Dynamic
navigation.dispatch(
CommonActions.preload('Profile', { user: 'jane' })
);
navigation.dispatch(
CommonActions.preload('Profile', { user: 'jane' })
);
预加载屏幕意味着屏幕将在后台渲染。屏幕中的所有组件都将被安装,并且 useEffect
钩子将被调用。当你想通过隐藏安装重型组件或加载数据的延迟来提高感知性能时,这将很有用。
¥Preloading a screen means that the screen will be rendered in the background. All the components in the screen will be mounted and the useEffect
hooks will be called. This can be useful when you want to improve the perceived performance by hiding the delay in mounting heavy components or loading data.
根据导航器的不同,preload
的工作方式可能有所不同:
¥Depending on the navigator, preload
may work differently:
-
在堆栈导航器(stack、原生堆栈)中,当你导航到屏幕时,屏幕将在屏幕外渲染并动画化。如果指定了
getId
,它将用于导航以识别预加载的屏幕。¥In a stack navigator (stack, native stack), the screen will be rendered off-screen and animated in when you navigate to it. If
getId
is specified, it'll be used for the navigation to identify the preloaded screen. -
在选项卡或抽屉导航器(底部标签、material 顶部标签、drawer 等)中,现有屏幕将被渲染为
lazy
设置为false
。在已渲染的屏幕上调用preload
不会产生任何效果。¥In a tab or drawer navigator (bottom tabs, material top tabs, drawer, etc.), the existing screen will be rendered as if
lazy
was set tofalse
. Callingpreload
on a screen that is already rendered will not have any effect.
当屏幕在堆栈导航器中预加载时,它会有一些限制:
¥When a screen is preloaded in a stack navigator, it will have a few limitations:
-
它无法分派导航操作(例如
navigate
、goBack
等)。¥It can't dispatch navigation actions (e.g.
navigate
,goBack
, etc.). -
它无法使用
navigation.setOptions
更新选项。¥It can't update options with
navigation.setOptions
. -
它无法监听来自导航器的事件(例如
focus
、tabPress
等)。¥It can't listen to events from the navigator (e.g.
focus
,tabPress
, etc.).
导航到屏幕后,navigation
对象将更新。因此,如果你在 useEffect
钩子中有一个事件监听器,并且依赖于 navigation
,它将在屏幕导航到时添加任何监听器:
¥The navigation
object will be updated once you navigate to the screen. So if you have an event listener in a useEffect
hook, and have a dependency on navigation
, it will add any listeners when the screen is navigated to:
React.useEffect(() => {
const unsubscribe = navigation.addListener('tabPress', () => {
// do something
});
return () => {
unsubscribe();
};
}, [navigation]);
类似地,对于分派操作或更新选项,你可以在执行此操作之前检查屏幕是否处于焦点状态:
¥Similarly, for dispatching actions or updating options, you can check if the screen is focused before doing so:
if (navigation.isFocused()) {
navigation.setOptions({ title: 'Updated title' });
}
setParams
setParams
操作允许更新特定路由的参数。它需要以下参数:
¥The setParams
action allows to update params for a certain route. It takes the following arguments:
-
params
- object - required - 新参数将合并到现有的路由参数中。¥
params
- object - required - New params to be merged into existing route params.
- Static
- Dynamic
navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
如果要为特定路由设置参数,可以添加引用路由键的 source
属性:
¥If you want to set params for a particular route, you can add a source
property referring to the route key:
- Static
- Dynamic
navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
source: route.key,
});
navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
source: route.key,
});
如果 source
属性显式设置为 undefined
,它将设置焦点路由的参数。
¥If the source
property is explicitly set to undefined
, it'll set the params for the focused route.