5.1 三种导航器与双端导航习惯


5.1 三种导航器与双端导航习惯

本节摘要:导航器是「管理一组屏幕及其历史的容器」——栈式管纵深、标签管并列、抽屉管收纳。本节建立导航器的嵌套心智模型,讲清三种容器的分工与混用原则,并正面处理移动导航最大的双端差异:iOS 的边缘滑动返回与 Android 的系统返回键。这节是骨架工程:骨架歪了,后面参数与深链都会跟着别扭。

导航器不是页面,是页面住的楼

先立住一个心智模型:屏幕(Screen)是内容,导航器(Navigator)是装屏幕的容器,容器还能套容器——标签导航器的每个标签位里可以住一个栈式导航器,栈里的某个屏幕里又可以再开一层标签。整棵结构像一栋楼:标签是楼层指引,栈是每层的走廊,屏幕是房间。用户「返回」时走的是走廊的历史记录,而不是楼层的——这两个概念分清,返回行为的一切怪象都能解释。

三种导航器的分工可以这样记。栈式(Stack)管纵深:列表进详情、详情进编辑,后进先出的历史栈,是使用频率最高的容器;标签(Tab)管并列:首页、发现、我的这些平级入口,用户在并列关系间来回横跳,切换不保留前进语义;抽屉(Drawer)管收纳:低频但全局的入口(设置、关于)收进侧边抽屉,按需拉出。混用原则一句话:并列关系用标签,纵深关系用栈,低频入口进抽屉——把「首页套标签、标签每个格子套栈」这个最常见组合用熟,百分之八十的应用骨架就定型了。下面是最小可运行的骨架代码:

import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { Text } from 'react-native'; const Stack = createNativeStackNavigator(); const Tab = createBottomTabNavigator(); function HomeStack() { return ( <Stack.Navigator> <Stack.Screen name="HomeList" component={HomeList} options={{ title: '首页' }} /> <Stack.Screen name="Detail" component={Detail} options={{ title: '详情' }} /> </Stack.Navigator> ); } function App() { return ( <NavigationContainer> <Tab.Navigator> <Tab.Screen name="HomeTab" component={HomeStack} options={{ title: '首页' }} /> <Tab.Screen name="MineTab" component={Mine} options={{ title: '我的' }} /> </Tab.Navigator> </NavigationContainer> ); } const HomeList = () => <Text>列表页:从这里 push 进 Detail</Text>; const Detail = () => <Text>详情页:走廊里的第二个房间</Text>; const Mine = () => <Text>我的:与首页并列的标签</Text>;

注意结构里的层次语义:Detail 住在「首页标签的栈」里,而不是根栈里——这决定了用户切到「我的」标签再切回来时,首页的走廊历史原样保留。嵌套结构本身就是产品语义的表达。

图:嵌套导航的结构与返回路径

图:嵌套导航的结构与返回路径

返回:两套方言的一次性翻译

返回行为是双端导航习惯差异的震中。iOS 没有系统返回键,习惯由「左上返回按钮加左缘右滑手势」构成,滑到一半松手页面会弹回——这种可中断的物理感是 iOS 用户的肌肉记忆;Android 有系统返回键(或侧滑返回手势),语义是「回退历史栈」,栈底再按就是退出应用。React Navigation 把两套方言统一成一层接口:栈式容器自动获得 iOS 手势返回,Android 的返回键事件则被映射为「弹出当前栈」的等效操作。

要在返回时做拦截——未保存表单的确认弹窗、播放页退出前停止播放——用容器提供的「返回前确认」能力注册监听,两端一次性生效,这就是统一接口的价值。但有一处必须显式提醒:Android 栈底按返回的默认行为是退出应用,产品上若想改成「双击退出」或「回首页」,要在根屏幕上挂自定义返回处理,别在深层页面写这段逻辑——否则用户会被困在楼里出不去。这属于「尊重方言」的差异:拦截能力是通用的,拦截后的出口语义要按端习惯设计。

拦截实现还有个时序细节:iOS 的滑返手势可以中途取消(滑一半松手),确认弹窗的触发时机要绑定「即将离开」而非「开始拖动」,否则用户刚想看看上一页是什么就被弹窗糊脸——判断方式是监听拦截回调里的取消标记,取消则当无事发生。这类细节在模拟器上测不出来,再次强调:两端真机是导航篇唯一可信的裁判。

完整案例:一次骨架返工的教训

背景:某社区应用初期把详情页直接挂在根栈上(与标签平级),运营随后要求「从『我的』标签的收藏列表也能进同一篇详情」。操作:最初的做法是在根栈复制了一份详情屏幕,导致同一详情有两个路由名、深链配置翻倍、返回行为出现两个版本——从首页进来返回去首页,从收藏进来返回却弹到了首页标签,bug 单开始堆积。重构方案:把详情移到一个独立的顶层栈容器(不隶属任何标签),两端入口都指向同一路由;返回行为用「来源感知」处理——带来源参数时返回到来源页,无来源时走默认回退。结果:路由收敛为一处,深链配置减半,返回行为可预期。解读:骨架阶段的偷懒会在血脉阶段加倍还债——「屏幕该住在哪栋楼」是产品语义决策,不是技术随机项。变式:类似地,全屏弹层(登录、播放器)适合独立的模态栈,与主内容的历史隔离,避免「关掉弹层却退出了页面」的怪象。

本节要点回顾

  • 导航器是容器不是页面:标签管并列、栈管纵深、抽屉管收纳,结构即产品语义;
  • 嵌套决定历史归属:屏幕住在哪层栈,返回就沿哪条走廊走,切换标签不清历史;
  • 返回是双端方言:iOS 滑动手势、Android 返回键,统一接口一次拦截两端生效;
  • 栈底返回即退出:改「双击退出」要写在根屏幕,别把用户困在楼里;
  • 公共屏幕独立成栈:多入口的详情放顶层容器,杜绝复制路由的返工。

楼盖好了,下一节铺管线:参数怎么传、返回值怎么带、导航状态怎么类型化。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U