ArkUI NavDestination:导航页要有自己的职责
【摘要】 今天我们把 NavDestination 单独拎出来看。 Navigation 负责管栈,但真正展示内容的是 NavDestination。如果目标页只是一堆随手写进去的组件,标题、参数、返回都散在外面,后面维护会很难受。我们这次做一个最小文章列表,点进去后由目标页自己接住参数、设置标题,并负责返回。 列表页只负责选择
ArkUI NavDestination:导航页要有自己的职责
今天我们把 NavDestination 单独拎出来看。
Navigation 负责管栈,但真正展示内容的是 NavDestination。如果目标页只是一堆随手写进去的组件,标题、参数、返回都散在外面,后面维护会很难受。我们这次做一个最小文章列表,点进去后由目标页自己接住参数、设置标题,并负责返回。
列表页只负责选择
列表页里准备两条内容,点击后压入同一个目标页:
this.pathStack.pushPathByName(item.name, new NavDestinationParam(item.title, item.summary, item.author))
这里传的是轻量参数。别把函数、上下文对象、大块业务对象塞进去。目标页拿不到参数时,也要能展示缺省内容。
目标页负责承接
目标页用 NavDestination 包住内容:
NavDestination() {
// 详情内容
}
.title(this.titleText())
这一步让目标页有自己的导航标题,而不是让外层页面到处替它管理。
onReady 里拿回 pathStack
目标页需要返回时,用 onReady 拿到当前目的地所属的导航栈:
.onReady((context: NavDestinationContext) => {
this.pathStack = context.pathStack
})
这样按钮里直接 this.pathStack.pop() 就能回到上一个目的地。这个 Demo 不讲生命周期监听、拦截器、自定义转场,也不做系统路由表;我们先把目标页自己的职责写顺。
运行后看什么
进入案例页后,点任意文章卡片。你会看到目标页标题跟着参数变化,正文也来自参数;如果以后参数缺失,页面也有默认文案兜底。
你平时写详情页时,标题和返回逻辑更喜欢放在列表页外层,还是放回详情页自己管理?这个选择会直接影响后面页面拆分的舒服程度。
完整代码
class NavDestinationArticle {
name: string
title: string
summary: string
author: string
color: string
bgColor: string
constructor(name: string, title: string, summary: string, author: string, color: string, bgColor: string) {
this.name = name
this.title = title
this.summary = summary
this.author = author
this.color = color
this.bgColor = bgColor
}
}
class NavDestinationParam {
title: string
summary: string
author: string
constructor(title: string, summary: string, author: string) {
this.title = title
this.summary = summary
this.author = author
}
}
@Entry
@Component
struct ArkUINavDestinationDemo {
private pathStack: NavPathStack = new NavPathStack()
private articles: NavDestinationArticle[] = [
new NavDestinationArticle('ArticleDetail', '页面标题别写死', '目标页拿到参数后,标题和内容都要能给出缺省值。', 'ArkUI Notes', '#7C3AED', '#F5F3FF'),
new NavDestinationArticle('ArticleDetail', '返回别到处找 router', 'NavDestination 里通过 onReady 拿到 context.pathStack,再决定怎么返回。', 'Navigation Lab', '#C2410C', '#FFF7ED')
]
@Builder
destinationMap(name: string, param: Object) {
if (name === 'ArticleDetail') {
ArticleDestinationPage({ param: param as NavDestinationParam })
}
}
@Builder
articleCard(item: NavDestinationArticle) {
Column({ space: 10 }) {
Row() {
Text(item.author)
.fontSize(12)
.fontColor(item.color)
.padding({ left: 10, right: 10, top: 4, bottom: 4 })
.backgroundColor('#FFFFFF')
.borderRadius(12)
Blank()
}
.width('100%')
Text(item.title)
.fontSize(20)
.fontWeight(700)
.fontColor('#0F172A')
Text(item.summary)
.fontSize(14)
.fontColor('#475569')
.lineHeight(21)
Button() {
Text('打开详情')
.fontSize(14)
.fontColor('#FFFFFF')
}
.width(120)
.height(38)
.borderRadius(19)
.backgroundColor(item.color)
.onClick(() => {
this.pathStack.pushPathByName(item.name, new NavDestinationParam(item.title, item.summary, item.author))
})
}
.width('100%')
.alignItems(HorizontalAlign.Start)
.padding(16)
.backgroundColor(item.bgColor)
.borderRadius(8)
}
build() {
Navigation(this.pathStack) {
Scroll() {
Column({ space: 16 }) {
Text('ArkUI NavDestination')
.width('100%')
.fontSize(28)
.fontWeight(800)
.fontColor('#0F172A')
Text('NavDestination 是 Navigation 栈里的目标页。它应该负责自己的标题、内容、返回和参数缺省。')
.width('100%')
.fontSize(14)
.fontColor('#475569')
.lineHeight(22)
Column({ space: 8 }) {
Text('这一页只做一件事')
.fontSize(16)
.fontWeight(700)
.fontColor('#0F172A')
Text('列表页只负责选择文章;详情页自己用 NavDestination 承接标题、内容和返回逻辑。')
.fontSize(13)
.fontColor('#64748B')
.lineHeight(20)
}
.width('100%')
.padding(14)
.backgroundColor('#F8FAFC')
.borderRadius(8)
ForEach(this.articles, (item: NavDestinationArticle) => {
this.articleCard(item)
}, (item: NavDestinationArticle) => item.title)
}
.width('100%')
.padding(20)
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
.title('NavDestination')
.titleMode(NavigationTitleMode.Mini)
.mode(NavigationMode.Auto)
.navDestination(this.destinationMap)
}
}
@Component
struct ArticleDestinationPage {
param: NavDestinationParam = new NavDestinationParam('未命名页面', '这条内容没有拿到参数,所以先展示缺省文案。', 'Unknown')
private pathStack: NavPathStack = new NavPathStack()
private titleText(): string {
return this.param.title.length > 0 ? this.param.title : '未命名页面'
}
private summaryText(): string {
return this.param.summary.length > 0 ? this.param.summary : '这条内容没有拿到参数,所以先展示缺省文案。'
}
private authorText(): string {
return this.param.author.length > 0 ? this.param.author : 'Unknown'
}
build() {
NavDestination() {
Column({ space: 16 }) {
Text(this.authorText())
.fontSize(13)
.fontColor('#7C3AED')
.padding({ left: 10, right: 10, top: 4, bottom: 4 })
.backgroundColor('#F5F3FF')
.borderRadius(12)
Text(this.titleText())
.fontSize(28)
.fontWeight(800)
.fontColor('#0F172A')
Text(this.summaryText())
.fontSize(15)
.fontColor('#475569')
.lineHeight(23)
Column({ space: 8 }) {
Text('这个目标页做了什么')
.fontSize(16)
.fontWeight(700)
.fontColor('#0F172A')
Text('它用 title 设置导航栏标题,用 onReady 拿到 NavDestinationContext,再通过 context.pathStack 完成返回。')
.fontSize(13)
.fontColor('#64748B')
.lineHeight(20)
}
.width('100%')
.padding(14)
.backgroundColor('#F8FAFC')
.borderRadius(8)
Button() {
Text('返回列表')
.fontSize(15)
.fontColor('#FFFFFF')
}
.width('100%')
.height(44)
.borderRadius(22)
.backgroundColor('#7C3AED')
.onClick(() => {
this.pathStack.pop()
})
}
.width('100%')
.height('100%')
.padding(20)
.alignItems(HorizontalAlign.Start)
.backgroundColor('#FFFFFF')
}
.title(this.titleText())
.onReady((context: NavDestinationContext) => {
this.pathStack = context.pathStack
})
}
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)