【方舟UI框架】Navigation

Navigation 是路由导航的根视图容器,一般作为页面(@Entry)的根容器,包括单栏(Stack)、分栏(Split)和自适应(Auto)三种显示模式。一次开发,多端部署场景下,Navigation组件能够自动适配窗口显示大小,在窗口较大的场景下自动切换分栏展示效果。

TypeScript 复制代码
Navigation() {
  // ...
}
.mode(NavigationMode.Auto) // 自适应
.mode(NavigationMode.Split) // 分栏
.mode(NavigationMode.Stack) // 单栏

Navigation组件主要包含​导航页和子页。导航页由标题栏(包含菜单栏)、内容区和工具栏组成,可以通过hideNavBar属性进行隐藏,导航页不存在路由栈中,与子页,以及子页之间可以通过路由操作进行切换。在API version 9上,Navigation需要配合NavRouter组件实现页面路由。从API version 10开始,更推荐使用NavPathStack实现页面路由。

显示模式

自适应模式

Navigation组件默认为自适应模式,此时mode属性为NavigationMode.Auto。自适应模式下,当页面宽度大于等于一定阈值( API version 9及以前:520vp,API version 10及以后:600vp )时,Navigation组件采用分栏模式,反之采用单栏模式。

单页面模式

单页面模式适用于窄屏设备,发生路由跳转时,整个页面都会被替换。

分栏模式

分栏模式适用于宽屏设备 ,分为左右两部分,发生路由跳转时,只有右边子页会被替换

路由操作

Navigation路由相关的操作都是基于导航控制器 NavPathStack提供的方法进行,每个Navigation都需要创建并传入一个NavPathStack对象,用于管理页面。Navigation中的NavDestination页面存在于NavPathStack中,以栈的结构管理,称为路由栈。

TypeScript 复制代码
@Entry
@Component
struct Index {
  // 创建一个导航控制器对象并传入Navigation
  pageStack: NavPathStack = new NavPathStack();

  build() {
    Navigation(this.pageStack) {
    }
    .title('Main')
  }
}

页面跳转

NavPathStack通过Push相关的接口去实现页面跳转的功能,主要分为以下三类:

普通跳转

通过页面的name去跳转,并可以携带param。

TypeScript 复制代码
this.pageStack.pushPath({ name: "PageOne", param: "PageOne Param" });
this.pageStack.pushPathByName("PageOne", "PageOne Param");

带返回回调的跳转

跳转时添加onPop回调,能在页面出栈时获取返回信息,并进行处理。

TypeScript 复制代码
this.pageStack.pushPathByName('PageOne', "PageOne Param", (popInfo) => {
  console.log('Pop page name is: ' + popInfo.info.name + ', result: ' + JSON.stringify(popInfo.result));
});

带错误码的跳转

跳转结束会触发异步回调,返回错误码信息。

TypeScript 复制代码
this.pageStack.pushDestination({name: "PageOne", param: "PageOne Param"})
  .catch((error: BusinessError) => {
    console.error(`Push destination failed, error code = ${error.code}, error.message = ${error.message}.`);
  }).then(() => {
    console.info('Push destination succeed.');
  });
this.pageStack.pushDestinationByName("PageOne", "PageOne Param")
  .catch((error: BusinessError) => {
    console.error(`Push destination failed, error code = ${error.code}, error.message = ${error.message}.`);
  }).then(() => {
    console.info('Push destination succeed.');
  });

页面返回

NavPathStack通过Pop相关接口去实现页面返回功能。

TypeScript 复制代码
// 返回到上一页
this.pageStack.pop();
// 返回到上一个PageOne页面
this.pageStack.popToName("PageOne");
// 返回到索引为1的页面
this.pageStack.popToIndex(1);
// 返回到根首页(清除栈中所有页面)
this.pageStack.clear();

页面替换

NavPathStack通过Replace相关接口去实现页面替换功能。

TypeScript 复制代码
// 将栈顶页面替换为PageOne
this.pageStack.replacePath({ name: "PageOne", param: "PageOne Param" });
this.pageStack.replacePathByName("PageOne", "PageOne Param");
// 带错误码的替换,跳转结束会触发异步回调,返回错误码信息
this.pageStack.replaceDestination({name: "PageOne", param: "PageOne Param"})
  .catch((error: BusinessError) => {
    console.error(`Replace destination failed, error code = ${error.code}, error.message = ${error.message}.`);
  }).then(() => {
    console.info('Replace destination succeed.');
  })

页面删除

NavPathStack通过Remove相关接口去实现删除路由栈中特定页面的功能。

TypeScript 复制代码
// 删除栈中name为PageOne的所有页面
this.pageStack.removeByName("PageOne");
// 删除指定索引的页面
this.pageStack.removeByIndexes([1, 3, 5]);
// 删除指定id的页面
this.pageStack.removeByNavDestinationId("1");

移动页面

NavPathStack通过Move相关接口去实现移动路由栈中特定页面到栈顶的功能。

TypeScript 复制代码
// 移动栈中name为PageOne的页面到栈顶
this.pageStack.moveToTop("PageOne");
// 移动栈中索引为1的页面到栈顶
this.pageStack.moveIndexToTop(1);

参数获取

NavDestination子页第一次创建时会触发onReady回调,可以获取此页面对应的参数。

TypeScript 复制代码
@Component
struct Page01 {
  pathStack: NavPathStack | undefined = undefined;
  pageParam: string = '';

  build() {
    NavDestination() {
      // ...
    }.title('Page01')
    .onReady((context: NavDestinationContext) => {
      this.pathStack = context.pathStack;
      this.pageParam = context.pathInfo.param as string;
    })
  }
}

NavDestination组件中可以通过设置onResult接口,接收返回时传递的路由参数。

TypeScript 复制代码
class NavParam {
  desc: string = 'navigation-param'
}

@Component
struct DemoNavDestination {
  // ...
  build() {
    NavDestination() {
      // ...
    }
    .onResult((param: Object) => {
      if (param instanceof NavParam) {
        console.log('TestTag', 'get NavParam, its desc: ' + (param as NavParam).desc);
        return;
      }
      console.log('TestTag', 'param not instance of NavParam');
    })
  }
}

其他业务场景,可以通过主动调用NavPathStack的Get相关接口去获取指定页面的参数。

TypeScript 复制代码
// 获取栈中所有页面name集合
this.pageStack.getAllPathName();
// 获取索引为1的页面参数
this.pageStack.getParamByIndex(1);
// 获取PageOne页面的参数
this.pageStack.getParamByName("PageOne");
// 获取PageOne页面的索引集合
this.pageStack.getIndexByName("PageOne");

路由拦截

NavPathStack提供了setInterception方法,用于设置Navigation页面跳转拦截回调。该方法需要传入一个NavigationInterception对象,该对象包含三个回调函数:

无论是哪个回调,在进入回调时路由栈都已经发生了变化。

开发者可以在willShow回调中通过修改路由栈来实现路由拦截重定向的能力。

TypeScript 复制代码
this.pageStack.setInterception({
  willShow: (from: NavDestinationContext | "navBar", to: NavDestinationContext | "navBar",
    operation: NavigationOperation, animated: boolean) => {
    if (typeof to === "string") {
      console.log("target page is navigation home page.");
      return;
    }
    // 将跳转到PageTwo的路由重定向到PageOne
    let target: NavDestinationContext = to as NavDestinationContext;
    if (target.pathInfo.name === 'PageTwo') {
      target.pathStack.pop();
      target.pathStack.pushPathByName('PageOne', null);
    }
  }
})
相关推荐
早八睡不醒午觉睡不够的程序猿15 小时前
Vue DevTools 调试提示
前端·javascript·vue.js
恋猫de小郭15 小时前
基于 Dart 的 Terminal UI ,pixel_prompt 这个 TUI 库了解下
android·前端·flutter
天天向上102415 小时前
vue el-form 自定义校验, 校验用户名调接口查重
前端·javascript·vue.js
忧郁的蛋~15 小时前
前端实现网页水印防移除的实战方案
前端
喝奶茶的Blair15 小时前
PHP应用-组件框架&前端模版渲染&三方插件&富文本编辑器&CVE审计(2024小迪安全DAY30笔记)
前端·安全·php
浪潮行舟15 小时前
WebGIS:在 Vue 2 项目中使用 Mapbox 时,如果需要加载的 GIS 数据量过大,怎么让接口一次性获取的geojson数据分批加载
前端·javascript·vue.js
susu108301891116 小时前
css中的vm和vh,页面滚动的卡片网页
前端·css
IT_陈寒16 小时前
⚡️Vite 5重磅升级:10个性能优化技巧让你的项目提速300%!🚀
前端·人工智能·后端
速易达网络17 小时前
React搭建应用
前端·react.js·前端框架