本节目标· 掌握 Navigation 组件的完整架构NavBar、NavDestination、NavPathStack 的职责与协作方式· 理解 Navigation 的单栏、分栏、自适应三种显示模式能够根据设备宽度自动切换布局· 掌握 Tabs 选项卡的基础用法包括 TabContent 与 tabBar 的配合、自定义 tabBar 的实现· 掌握 SideBarContainer 侧边栏容器的 Embed 与 Overlay 两种显示模式能够实现抽屉式导航· 了解多页面应用的路由架构设计原则能够为中等规模应用规划合理的页面组织方式· 能够综合运用 Navigation、Tabs、SideBarContainer 构建一个完整的多页面应用骨架一、Navigation 完整架构1.1 三大核心概念Navigation 组件是 ArkUI 推荐的组件级路由方案其整体架构由三个核心部分组成。Navigation导航根视图容器 所有的导航页面都被此容器包裹提供分栏显示的能力一般用作全局的根容器。Navigation 管理了标题栏、内容区和工具栏内容区用于显示用户自定义页面的内容并支持页面的路由能力。NavDestination子页面容器 导航的所有页面路由操作均是针对 NavDestination 的操作。NavDestination 是 Navigation 子页面的根容器用于承载子页面的特殊属性和生命周期可以配置独立的标题栏、菜单栏与工具栏等属性使用方法与 Navigation 一致。NavPathStack导航控制器 用于管理 NavDestination 页面栈封装了各种控制页面跳转的接口支持继承后重写需与 Navigation 绑定使用。整个 Navigation 容器应复用同一个 NavPathStack不要在每次 build 或点击时重新创建。1.2 单栏、分栏与自适应模式Navigation 提供三种显示模式通过 mode 属性控制。单栏模式Stack 当 Navigation 容器宽度小于 600vp 时建议使用。此模式下发生路由跳转时整个页面都会被替换。分栏模式Split 当 Navigation 容器宽度大于等于 600vp 时建议使用。此模式下 Navigation 分为左右两部分左侧为导航栏NavBar右侧为子页面NavDestination。发生路由跳转时只有右边子页会被替换。自适应模式Auto 默认值。在该模式下会自动监听屏幕属性当为折叠屏或平板时默认分栏显示在折叠状态或普通手机时可为单栏显示。1.3 基础用法示例以下是一个带完整路由跳转能力的 Navigation 示例EntryComponentstruct NavigationBasic{Provide(pageStack)pageStack:NavPathStacknewNavPathStack()BuilderpageMap(name:string,param:object){if(namedetail){DetailPage({itemId:paramasstring})}}build(){Navigation(this.pageStack){// NavBar 内容区首页Column({space:16}){Text(首页).fontSize(24).fontWeight(FontWeight.Bold)ForEach([商品A,商品B,商品C],(item:string){Row(){Text(item).fontSize(16).layoutWeight(1)Text(查看 →).fontSize(14).fontColor(#007DFF)}.width(100%).padding(16).backgroundColor(Color.White).borderRadius(10).onClick((){this.pageStack.pushPathByName(detail,item)})})}.width(100%).height(100%).padding(16).backgroundColor(#F5F5F5)}.title(我的应用).mode(NavigationMode.Auto)// 自适应模式.navDestination(this.pageMap).hideNavBar(false)}}Componentstruct DetailPage{Consume(pageStack)pageStack:NavPathStack itemId:stringbuild(){NavDestination(){Column({space:20}){Text(详情页${this.itemId}).fontSize(22)Text(这里是子页面内容区域).fontSize(15).fontColor(#666)Button(返回).type(ButtonType.Capsule).onClick((){this.pageStack.pop()})}.width(100%).height(100%).justifyContent(FlexAlign.Center)}.title(详情)}}关键理解Provide 和 Consume 实现 NavPathStack 的跨组件共享避免在多个组件间逐层传递。navDestination 方法将页面名称映射到具体的 NavDestination 组件。跳转时 pushPathByName 传入名称和参数子页面通过 pathInfo.param 或构造参数接收。1.4 NavPathStack 常用操作入栈pushPathByName(name, param) 携带参数跳转pushPathByName(name, param, onPop) 带返回回调的跳转。返回结果不要写全局变量可在 pop 时带 result或由共享 ViewModel 保存业务状态。出栈pop() 返回上一页popToName(name) 返回指定页面popToIndex(index) 返回到指定索引的页面。替换replacePath(info) 或 replacePathByName(name, param) 替换当前页面。清空clear() 清空路由栈。路由拦截支持通过 setInterception 做路由拦截。二、Tabs 选项卡2.1 基础结构Tabs 组件通过页签进行内容视图切换每个页签对应一个内容视图。Tabs 的页面组成包含两个部分TabContent内容页和 TabBar导航页签栏。根据不同的导航类型布局可以分为底部导航、顶部导航、侧边导航其导航栏分别位于底部、顶部和侧边。EntryComponentstruct TabsBasic{StatecurrentIndex:number0build(){Tabs({barPosition:BarPosition.End,index:this.currentIndex}){TabContent(){Column(){Text(首页内容).fontSize(24)}.width(100%).height(100%).justifyContent(FlexAlign.Center)}.tabBar(this.tabBuilder(首页,0))TabContent(){Column(){Text(发现内容).fontSize(24)}.width(100%).height(100%).justifyContent(FlexAlign.Center)}.tabBar(this.tabBuilder(发现,1))TabContent(){Column(){Text(我的内容).fontSize(24)}.width(100%).height(100%).justifyContent(FlexAlign.Center)}.tabBar(this.tabBuilder(我的,2))}.onChange((index:number){this.currentIndexindex}).barHeight(56).width(100%).height(100%)}BuildertabBuilder(title:string,index:number){Column({space:4}){Image(this.currentIndexindex?$r(app.media.icon_tab_active):$r(app.media.icon_tab_normal)).width(24).height(24)Text(title).fontSize(11).fontColor(this.currentIndexindex?#007DFF:#999999)}.width(100%).height(56).justifyContent(FlexAlign.Center)}}关键规则TabContent 组件不支持设置通用宽度属性其宽度默认撑满 Tabs 父组件不支持设置通用高度属性其高度由 Tabs 父组件高度与 TabBar 组件高度决定。每一个 TabContent 对应的内容需要有一个页签可以通过 tabBar 属性进行配置。2.2 自定义 TabBar标准 Tabs 组件不支持在 tabBar 中添加其他组件如“”号按钮但通过设置 barHeight(0) 隐藏原生 TabBar再使用 Stack 将自定义 tabBar 放到上层即可实现。自定义 Tabs 的典型场景包括在 tabBar 中添加操作按钮、实现可滚动的标签栏、创建完全自定义样式的导航栏。// 自定义 tabBar 的核心思路Stack({alignContent:Alignment.TopStart}){// 自定义 tabBar 区域Scroll(){Row(){ForEach(this.tabArray,(item:number,index:number){this.tab(Tabitem,item,index)})Text().width(36).height(50).fontSize(28).onClick((){this.tabArray.push(this.lastTabIndex)})}}.scrollable(ScrollDirection.Horizontal).scrollBar(BarState.Off)// Tabs 内容区barHeight(0) 隐藏原生 tabBarTabs({barPosition:BarPosition.Start,controller:this.controller}){ForEach(this.tabArray,(item:number){TabContent(){Text(页面 item).fontSize(30)}})}.barHeight(0)}2.3 Tabs 与滚动容器的双向联动从 API 13 起UIContext.bindTabsToScrollable() 可以将 TabsController 和 Scroll/List/Grid 的 Scroller 绑定起来内容上滑时自动隐藏 TabBar下滑时自动显示。// 在 UIContext 中绑定this.getUIContext().bindTabsToScrollable(this.tabsController,this.scroller)this.getUIContext().bindTabsToNestedScrollable(this.tabsController,this.nestedScroller)三、SideBarContainer 侧边栏容器3.1 基本结构与显示模式SideBarContainer 提供侧边栏可以显示和隐藏的容器通过子组件定义侧边栏和内容区。第一个子组件表示侧边栏第二个子组件表示内容区必须且仅包含 2 个子组件。SideBarContainer 支持两种显示模式Embed并排式 侧边栏嵌入到组件内和内容区并列显示适用于需要同时展示侧边栏和内容区的场景平板、PC 大屏。整体容器大小不变时显示侧边栏会导致内容区缩小隐藏侧边栏会扩大内容区。Overlay覆盖式 侧边栏覆盖在内容区上方不影响内容区布局适用于手机等小屏设备。侧边栏隐藏时不占据空间唤出时悬浮在内容之上。EntryComponentstruct SideBarDemo{StateshowSideBar:booleantruebuild(){SideBarContainer(SideBarContainerType.Embed){// 第一个子组件侧边栏Column({space:12}){Text(导航菜单).fontSize(18).fontWeight(FontWeight.Bold).margin({bottom:12})ForEach([首页,发现,消息,设置],(item:string,index:number){Row({space:12}){Text(item).fontSize(15)}.width(100%).padding(12).borderRadius(8).backgroundColor(index0?#E8F0FE:Color.Transparent)})}.width(220).height(100%).padding(16).backgroundColor(#F8F9FA)// 第二个子组件内容区Column(){Text(主内容区域).fontSize(24)}.width(100%).height(100%).justifyContent(FlexAlign.Center)}.showSideBar(this.showSideBar).showControlButton(true)// 显示控制按钮.sideBarWidth(220).minSideBarWidth(180).minContentWidth(360).onChange((value:boolean){this.showSideBarvalue}).width(100%).height(100%)}}3.2 关键属性showSideBar设置是否显示侧边栏默认为 true。sideBarWidth / minSideBarWidth / maxSideBarWidth控制侧边栏宽度。组件尺寸小于 minContentWidth minSideBarWidth 且未设置 showSideBar 时侧边栏自动隐藏。showControlButton是否显示控制按钮默认为 true。可以通过 controlButton 属性自定义控制按钮的图标和位置。sideBarPosition设置侧边栏的位置可选 Start左侧或 End右侧。四、多页面架构设计建议4.1 页面数量增长带来的问题在 HarmonyOS 项目中页面数量一旦超过 5 个如果没有清晰的多页面架构设计很快就会出现以下问题路由混乱页面之间互相跳转像“意大利面”页面状态靠参数硬传改一个页面牵一片生命周期逻辑分散难以统一管理后期加新功能不敢动老代码。4.2 推荐的架构组织方式根容器用 Navigation将 Navigation 作为应用根容器所有页面跳转通过 NavPathStack 管理。Navigation 具备更强的一次开发多端部署能力可以进行更加灵活的页面栈操作同时支持更丰富的动效和生命周期。主页面用 Tabs应用的主框架首页、发现、消息、我的用 Tabs 组织每个 Tab 内部再嵌套 Navigation 实现该 Tab 下的页面跳转。设置页面用 SideBarContainer如果应用有侧边菜单需求如设置、帮助中心使用 SideBarContainer 或 Navigation 的分栏模式实现。跨模块跳转用 Router如果项目包含多个模块HAP主项目要跳转到其他模块的页面时使用 Router 实现跨模块跳转。单模块应用推荐全部使用 Navigation。4.3 综合架构示例EntryComponentstruct AppRoot{Provide(mainStack)mainStack:NavPathStacknewNavPathStack()BuilderpageMap(name:string){if(namesettings){SettingsPage()}elseif(nameprofile){ProfilePage()}}build(){Navigation(this.mainStack){// 主框架TabsTabs({barPosition:BarPosition.End}){TabContent(){HomePage()}.tabBar(this.mainTab(首页,0))TabContent(){DiscoverPage()}.tabBar(this.mainTab(发现,1))TabContent(){MessagePage()}.tabBar(this.mainTab(消息,2))TabContent(){ProfilePage()}.tabBar(this.mainTab(我的,3))}.barHeight(56)}.title(应用名称).mode(NavigationMode.Auto).navDestination(this.pageMap).hideNavBar(false)}BuildermainTab(title:string,index:number){Column({space:4}){Text(title).fontSize(11).fontColor(this.currentTabIndexindex?#007DFF:#999)}.width(100%).height(56).justifyContent(FlexAlign.Center)}}五、多元化习题习题 1判断题题目在 Navigation 架构中NavPathStack 可以在每次点击跳转时重新创建不影响路由功能。答案错误解读整个 Navigation 容器应复用同一个 NavPathStack不要在每次 build 或点击时重新创建。每次重新创建会导致路由栈信息丢失页面返回逻辑失效。习题 2单选题题目以下哪个组件是 Navigation 子页面的根容器A. NavBarB. NavPathStackC. NavDestinationD. Navigation答案C解读NavDestination 是 Navigation 子页面的根容器用于承载子页面的特殊属性和生命周期可以配置独立的标题栏、菜单栏与工具栏等属性。NavBar 是导航栏主页面NavPathStack 是导航控制器Navigation 是导航根视图容器。习题 3多选题题目关于 SideBarContainer以下说法正确的有多选A. 必须且仅包含 2 个子组件第一个是侧边栏第二个是内容区B. Embed 模式下侧边栏覆盖在内容区上方C. Overlay 模式下侧边栏不影响内容区布局D. 当容器尺寸小于 minContentWidth minSideBarWidth 且未设置 showSideBar 时侧边栏自动隐藏答案A、C、D解读SideBarContainer 必须且仅包含 2 个子组件第一个表示侧边栏第二个表示内容区选项 A 正确。Embed 模式下侧边栏嵌入到组件内与内容区并列显示Overlay 模式下侧边栏覆盖在内容区上方、不影响内容区布局选项 B 描述相反选项 C 正确。组件尺寸小于 minContentWidth minSideBarWidth 且未设置 showSideBar 时侧边栏自动隐藏选项 D 正确。习题 4代码填空题题目请补全以下 Navigation 代码实现点击按钮跳转到名称为 “detail” 的子页面。Navigation(this.pageStack){Button(查看详情).onClick((){// 在此处填写代码______________})}.navDestination(this.pageMap)答案this.pageStack.pushPathByName(‘detail’, null)解读pushPathByName 是 NavPathStack 的入栈方法第一个参数是 NavDestination 的名称第二个参数是传递的参数无参数时可传 null。习题 5代码改错题题目以下 Tabs 代码存在布局问题请指出问题并修正。Tabs(){TabContent(){Text(内容1)}.tabBar(标签1)}.height(100%)答案代码缺少 .width(‘100%’) 属性。TabContent 组件不支持设置通用宽度属性其宽度默认撑满 Tabs 父组件但 Tabs 组件本身如果没有设置宽度可能无法正确撑满页面。修正如下Tabs(){TabContent(){Text(内容1)}.tabBar(标签1)}.width(100%).height(100%)解读TabContent 的宽度默认撑满 Tabs 父组件但 Tabs 组件需要显式设置宽度以确保布局正确。习题 6简答题题目简述 Navigation 的单栏、分栏、自适应三种显示模式的区别及适用场景。答案单栏模式Stack在 Navigation 容器宽度小于 600vp 时建议使用此模式下发生路由跳转时整个页面都会被替换适合手机竖屏场景。分栏模式Split在容器宽度大于等于 600vp 时建议使用Navigation 分为左右两部分左侧为导航栏右侧为子页面路由跳转时只有右边子页会被替换适合平板、PC 大屏场景。自适应模式Auto为默认值会自动监听屏幕属性折叠屏或平板时默认分栏显示折叠状态或普通手机时可单栏显示适合需要一次开发多端部署的应用。解读Navigation 通过 mode 属性控制显示模式开发者可以将 mode 设置为 NavigationMode.Stack、NavigationMode.Split 或 NavigationMode.Auto实现不同设备形态下的自适应布局。习题 7简答题题目简述多页面应用中Navigation、Tabs、SideBarContainer 三种组件的典型协作方式。答案在典型的多页面应用中Navigation 作为应用根容器管理全局页面栈和跨页面的路由跳转。Tabs 作为主框架页面首页、发现、消息、我的的组织方式每个 Tab 内部可以再嵌套 Navigation 实现该 Tab 下的页面跳转。SideBarContainer 用于实现侧边菜单如设置、帮助中心在平板或 PC 大屏上以 Embed 模式并排显示在手机上以 Overlay 模式覆盖显示。三种组件各司其职Navigation 管路由Tabs 管主框架SideBarContainer 管侧边导航。解读三种组件的协作方式取决于应用的具体需求。Navigation 是路由的底座Tabs 是主界面的骨架SideBarContainer 是辅助导航的扩展。开发者应根据页面结构合理组合使用避免过度嵌套导致的性能问题。六、本节知识点总结Navigation 完整架构由 Navigation根视图容器、NavDestination子页面容器和 NavPathStack导航控制器三部分组成。NavPathStack 管理页面栈支持 pushPathByName、pop、replacePath 等操作整个 Navigation 容器应复用同一个 NavPathStack。三种显示模式单栏模式Stack适合手机竖屏分栏模式Split适合平板大屏自适应模式Auto根据屏幕宽度自动切换。通过 mode 属性控制。Tabs 选项卡由 TabContent内容页和 TabBar导航栏组成支持底部、顶部、侧边三种导航位置。TabContent 宽度默认撑满 Tabs高度由 Tabs 高度和 TabBar 高度决定。标准 Tabs 不支持在 tabBar 中添加其他组件通过 barHeight(0) 隐藏原生 TabBar 可实现自定义导航栏。Tabs 与滚动联动API 13 起 bindTabsToScrollable() 可将 Tabs 与 Scroll/List/Grid 绑定内容上滑自动隐藏 TabBar下滑自动显示。SideBarContainer侧边栏容器第一个子组件是侧边栏第二个是内容区。Embed 模式并排显示适合大屏Overlay 模式覆盖显示适合小屏。支持通过 showSideBar、sideBarWidth、minContentWidth 等属性控制显隐和尺寸。多页面架构设计Navigation 作为根容器管路由Tabs 组织主框架页面SideBarContainer 实现侧边导航。跨模块跳转使用 Router单模块应用推荐全部使用 Navigation。下节预告第17课将进入 ArkUI 应用国际化与无障碍适配的学习涵盖多语言资源管理、RTL 布局适配、无障碍属性配置以及多设备适配的核心方法。
阅读完成 · 觉得有帮助?