鸿蒙组件导航和页面路由【华为根技术】

举报
tea_year 发表于 2025/07/30 17:11:19 2025/07/30
【摘要】 @Entry@Componentstruct NavigationExample { // 1. 创建导航(路由)对象 NavPathStack @Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack() private arr: number[] = [1, 2, 3]; // 2.创建配置路由的@Build...
@Entry
@Component
struct NavigationExample {
  // 1. 创建导航(路由)对象 NavPathStack
  @Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack()
  private arr: number[] = [1, 2, 3];

  // 2.创建配置路由的@Builder
  @Builder
  PageMap(name: string) {
    if (name === "page1") {
      pageOneTmp()
    } else if (name === "page2") {
      pageTwoTmp()
    } else if (name === "page3") {
      pageThreeTmp()
    }
  }

  build() {
    Column() {
      //3. 给Navigation导航组件配置路由对象
      Navigation(this.pageInfos) {
        TextInput({ placeholder: 'search...' })
          .width("90%")
          .height(40)
          .backgroundColor('#FFFFFF')

        List({ space: 12 }) {
          ForEach(this.arr, (item:number) => {
            ListItem() {
              Text("Page" + item)
                .width("100%")
                .height(72)
                .backgroundColor('#FFFFFF')
                .borderRadius(24)
                .fontSize(16)
                .fontWeight(500)
                .textAlign(TextAlign.Center)
                .onClick(()=>{
                  // 5. 此时就可以调用pageInfos对象的pushPath方法来实现路由跳转
                  // 执行pushPath时,会自动调用PageMap这个@Builder,并把name值传给PageMap
                  this.pageInfos.pushPath({ name: "page" + item})
                })
            }
          }, (item:number) => item.toString())
        }
        .width("90%")
        .margin({ top: 12 })
      }
      .title("主标题")

      
      // 4. 给Navigation配置路由Builder
      .navDestination(this.PageMap)
      
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

// PageOne.ets
@Component
export struct pageOneTmp {
  // 6. 在子组件中接收根组件传来的路由对象
  @Consume('pageInfos') pageInfos: NavPathStack;
  build() {
    // 7. 子组件必须用NavDestination作为根组件
    NavDestination() {
      Column() {
        Text("第一页")

        Text("第二页")
          .onClick(()=>{
            this.pageInfos.pushPath({name: 'page2'})
          })
      }.width('100%').height('100%')
    }
    // .title("NavDestinationTitle1")
    // .onBackPressed(() => {
    //   const popDestinationInfo = this.pageInfos.pop() // 弹出路由栈栈顶元素
    //   console.log('pop' + '返回值' + JSON.stringify(popDestinationInfo))
    //   return true
    // })
  }
}

// PageTwo.ets
@Component
export struct pageTwoTmp {
  @Consume('pageInfos') pageInfos: NavPathStack;
  build() {
    NavDestination() {
      Column() {
        Text("NavDestinationContent2")
      }.width('100%').height('100%')
    }.title("NavDestinationTitle2")
    .onBackPressed(() => {
      const popDestinationInfo = this.pageInfos.pop() // 弹出路由栈栈顶元素
      console.log('pop' + '返回值' + JSON.stringify(popDestinationInfo))
      return true
    })
  }
}

// PageThree.ets
@Component
export struct pageThreeTmp {
  @Consume('pageInfos') pageInfos: NavPathStack;
  build() {
    NavDestination() {
      Column() {
        Text("NavDestinationContent3")
      }.width('100%').height('100%')
    }.title("NavDestinationTitle3")
    .onBackPressed(() => {
      const popDestinationInfo = this.pageInfos.pop() // 弹出路由栈栈顶元素
      console.log('pop' + '返回值' + JSON.stringify(popDestinationInfo))
      return true
    })
  }
}

淘小说代码

Index.ets

import { End } from './End'
import { Rank } from './Rank'

@Entry
@Component
struct Index {
  @Provide("navPathStack") pageInfos: NavPathStack = new NavPathStack()

  @Builder PageMap(name: string){
    if (name === 'rank') {
      Rank()
    } else if (name === 'end') {
      End()
    } else if (name === 'free') {
      Free()
    }
  }
  build() {
    Navigation(this.pageInfos){
        Column(){
          Text("这是首页")

          Text("榜单")
            .onClick(()=>{
              this.pageInfos.pushPath({name: 'rank'})
            })

          Text("完结")
            .onClick(()=>{
              this.pageInfos.pushPath({name: 'end'})
            })
        }
    }
    .navDestination(this.PageMap)
  }
}

完结End.ets

@Component
export struct End {
  @Consume("navPathStack") pathInfos: NavPathStack
  build() {
    NavDestination(){
      Text("完结的内容")
      Text("榜单")
        .onClick(()=>{
            this.pathInfos.pushPath({name: 'rank'})
        })
        
       Text("回到首页")
          .onClick(()=>{
            // // 返回到根首页(清除栈中所有页面)
            this.pathInfos.clear() 
          })
    }
  }
}
  1. Navigation组件的属性

mode属性

设置单页面模式和分栏模式
三种选项: Auto | Stack | Split
1. NavigationMode.Auto 默认值 , 自动检测屏幕宽度, 小于600vp屏幕宽度,采用单页面模式,大于600vp自动分栏 (适配)
2. NavigationMode.Stack 无论何种屏幕宽度,都采用单页面模式
3. NavigationMode.Split 无论何种屏幕宽度,都采用分栏模式

titleMode属性

设置标题样式 三种选项: Mini | Full | Free
Navigation(){
  ...
}
.titleMode(NavigationTitleMode.Mini)
1. NavigationTitleMode.Mini 标题显示在最顶端
2. NavigationTitleMode.Full 强调型标题栏,用于一级页面需要突出标题的场景。
  1. NavigationTitleMode.Free 当内容为满一屏的可滚动组件时,标题随着内容向上滚动而缩小(子标题的大小不变、淡出)。向下滚动内容到顶时则恢复原样。

menus属性

设置菜单栏
menus支持Array<NavigationMenuItem>,使用Array<NavigationMenuItem>类型时,竖屏最多支持显示3个图标,横屏最多支持显示5个图标,多余的图标会被放入自动生成的更多图标。

注意: 图标放在ets的image子目录中, icon地址格式: 'image/startIcon.png'
struct Index {
 
  private menuList: Array<NavigationMenuItem> = [
    {'value': "分享", 'icon': "image/startIcon.png", 'action': () => {
        this.pageInfos.pushPath({ name: 'NavDestinationTitle1' })
      }},
    {'value': "技术", 'icon': "image/startIcon.png", 'action': () => {}},
    {'value': "问答", 'icon': "image/startIcon.png", 'action': () => {}},
    {'value': "文章1", 'icon': "image/startIcon.png", 'action': () => {}},
    {'value': "文章2", 'icon': "image/startIcon.png", 'action': () => {}}
  ]
  

  build() {
    Navigation(this.pageInfos) {
      
    }
    .menus(this.menuList)
  }
}

toolbarConfiguration属性

设置工具栏内容。不设置时不显示工具栏。
struct Index {
    private toolBarList: ToolbarItem[] = [
      {'value': "技术1", 'icon': "image/startIcon.png", 'action': () => {}},
      {'value': "技术2", 'icon': "image/startIcon.png", 'action': () => {}},
      {'value': "技术3", 'icon': "image/startIcon.png", 'action': () => {}},
      {'value': "技术4", 'icon': "image/startIcon.png", 'action': () => {}},
    ]
    ...
    
    build() {
        Navigation(this.pageInfos) {
          
        }
        .toolbarConfiguration(this.toolBarList)
  }
 }

hideTitleBar(true)

隐藏标题栏

hideToolBar(true)

隐藏底部工具栏
  1. 通过配置系统路由表实现导航

  • 在首页中不需要配置PageMap
  • 不需要配置navDestination属性
  • 但在每个子页面中需要创建@builder并导出
  • 需要配置route_map.json

1. 创建导航页 (首页)

Index.ets
@Entry()
@Component
struct Index {
  // 1. 创建路由栈NavPathStack以此来实现不同页面之间的跳转。
  @Provide('NavPathStack') pageInfos: NavPathStack = new NavPathStack()
   

  build() {
   // 2. 使用Navigation创建导航主页,并传入路由栈
    Navigation(this.pageInfos) {
      Scroll() {
         Text('跳转')
      }
    }
      .mode(NavigationMode.Stack)
      .height('100%')
      .hideToolBar(true)
      .hideTitleBar(true)
  }
}

2. 创建导航子页

Rank.ets
// 跳转页面入口函数
@Builder
export function RankBuilder(name: string, param: Object) {
  Rank()
}

Component
export struct Rank {
  @Consume('NavPathStack') pageInfos: NavPathStack;
  
  build() {
    NavDestination() {
      Column() {
        
      }
      .width('100%')
      .height('100%')
    }
    .hideTitleBar(true)
  }
}

配置route_map.json文件

【main】【resources】【base】【profile】
route_map.json
{
  "routerMap": [
    {
      "name": "rank",
      "pageSourceFile": "src/main/ets/pages/Rank.ets",
      "buildFunction": "RankBuilder",
      "data": {
        "description": "Rank"
      }
    },
    ...
  ]
}

4 .配置module.json5

【main】
module.json5
Module 模块
{
  "module": {
    "routerMap": "$profile:route_map",
    "requestPermissions": [{
      //设置申请网络权限
      "name": "ohos.permission.INTERNET"
    }],
    ...
  }
}

实现首页转场到榜单页(Rank)

Index.ets
@Entry()
@Component
struct Index {
  @Provide('NavPathStack') pageInfos: NavPathStack = new NavPathStack()
   
  build() {
  
    Navigation(this.pageInfos) {
      Scroll() {
         Text('跳转到榜单页')
         .onClick(() => {
              this.pageInfos.pushPath({ name: 'rank' })
          })
      }
    }
      .mode(NavigationMode.Stack)
      .height('100%')
      .hideToolBar(true)
      .hideTitleBar(true)
  }
}
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。