《uni-app跨平台开发完全指南》- 06 - 页面路由与导航

深入理解页面路由与导航

如果把组件比作应用的"血肉",那么路由导航就是应用的"筋骨"。他定义了用户在应用中的跳转路径,决定了应用的流程和用户体验。比如当你点击商品列表中的一件商品,它是如何平滑地跳转到商品详情页的?当你完成订单支付后,又是如何一步步返回首页的?这背后的一切,都离不开一个核心机制------路由与导航

本篇学习路径:

flowchart TD A[页面路由与导航] --> B[页面栈管理原理] A --> C[路由跳转方式对比] A --> D[传参与接收参数] A --> E[导航栏自定义配置] B --> B1[栈数据结构
LIFO后进先出] B --> B2[getCurrentPages
获取页面栈实例] C --> C1[navigateTo
保留当前页面跳转] C --> C2[redirectTo
关闭当前页面跳转] C --> C3[switchTab
跳转tabBar页面] C --> C4[reLaunch
关闭所有页面跳转] C --> C5[navigateBack
返回上一页面] D --> D1[URL拼接传参
?key=value&key2=value2] D --> D2[onLoad生命周期接收
options参数对象] E --> E1[pages.json全局配置
navigationBarTitleText等] E --> E2[页面级配置
覆盖全局配置] E --> E3[动态修改
setNavigationBarTitle] %% 连接关系 B2 -.-> C1 B2 -.-> C5 D1 -.-> C1 D1 -.-> C2 D1 -.-> C3 D1 -.-> C4 E3 -.-> D2 %% 样式定义 classDef root fill:#1a2a6c,color:#fff,stroke:#1a2a6c,stroke-width:2px classDef level1 fill:#b21f1f,color:#fff,stroke:#b21f1f classDef level2 fill:#fdbb2d,color:#333,stroke:#fdbb2d classDef level3 fill:#4CAF50,color:#fff,stroke:#4CAF50 class A root class B,C,D,E level1 class B1,B2,C1,C2,C3,C4,C5,D1,D2,E1,E2,E3 level2

一、 应用导航的底层逻辑:页面栈管理

在深入各种跳转API之前,我们必须先理解一个核心概念------页面栈(Page Stack)。这是后面所讲内容的基础。

1.1 什么是页面栈?

之前讲解Flutter时已经提到了,页面栈就好比一摞书。

  • 新打开一本书(页面) ,你就把它压(Push) 在这摞书的最上面。
  • 你想看下面那本书,就得把最上面这本拿掉(Pop),才能看到它。

在uni-app中,这个"放书"和"拿书"的过程,就是由页面栈来管理的。它是一个遵循 "后进先出(LIFO - Last In, First Out)" 原则的数据结构。

  • 压栈(Push) :每当使用类似 uni.navigateTo 的方法打开一个新页面时,这个新页面就会被压入栈顶,成为活动页面(Active Page),展示给用户。
  • 出栈(Pop) :每当用户点击左上角的返回按钮或调用 uni.navigateBack 方法时,栈顶的页面就会被弹出,此时,下面的页面就会成为新的活动页面,呈现给用户。
flowchart TD subgraph A [初始状态] direction TB subgraph StackA [页面栈] A1[页面A]:::top end StateA[用户正 viewing 页面A] end A -->|用户执行 uni.navigateTo
跳转到 页面B| B subgraph B [navigateTo 后] direction TB subgraph StackB [页面栈] B1[页面B]:::top B2[页面A] end StateB[用户正 viewing 页面B] end B -->|用户执行 uni.navigateTo
跳转到 页面C| C subgraph C [再次 navigateTo 后] direction TB subgraph StackC [页面栈] C1[页面C]:::top C2[页面B] C3[页面A] end StateC[用户正 viewing 页面C] end C -->|用户点击返回按钮
或执行 uni.navigateBack| D subgraph D [navigateBack 后] direction TB subgraph StackD [页面栈] D1[页面B]:::top D2[页面A] end StateD[用户正 viewing 页面B
页面C已被销毁] end classDef top fill:#e1f5fe;

一个简单的例子: 首页(Index) -> 商品列表(List) -> 商品详情(Detail)

这个过程的栈变化是:

  1. 启动App:栈 = [Index]
  2. 从首页跳转到列表页:栈 = [Index, List] (List被Push入栈)
  3. 从列表页跳转到详情页:栈 = [Index, List, Detail] (Detail被Push入栈)
  4. 从详情页返回:栈 = [Index, List] (Detail被Pop出栈)
  5. 再次返回:栈 = [Index] (List被Pop出栈)

1.2 如何获取和管理页面栈?

uni-app 提供了一个全局的 getCurrentPages() 方法来获取当前页面栈的实例数组。

这个数组:

  • 第一个元素是栈底页面(通常是应用的首页)。
  • 最后一个元素是栈顶页面(当前展示给用户的页面)。

在任何页面中,你都可以这样获取栈信息:

javascript 复制代码
// 在商品详情页(Detail.vue)的 methods 中
checkPageStack() {
  // 获取当前页面栈的实例数组
  const pages = getCurrentPages();
  console.log('当前页面栈:', pages);

  // 获取栈顶页面实例
  const currentPage = pages[pages.length - 1];
  console.log('当前页面实例:', currentPage);

  // 获取栈底页面实例(一般来说是首页)
  const firstPage = pages[0];
  console.log('首页实例:', firstPage);

  // 甚至可以获取上一个页面的实例,并直接调用其方法或数据
  const prevPage = pages[pages.length - 2]; // 上一个页面
  if (prevPage) {
    console.log('上一个页面:', prevPage);
    // 注意:这是一种页面间通信的方式,但需谨慎使用,确保prevPage存在且结构稳定
    // prevPage.someData = '来自详情页的数据'; // 直接修改上一个页面的数据
    // prevPage.someMethod(); // 直接调用上一个页面的方法
  }
}

getCurrentPages() 的应用场景:

  • 场景1:在任意页面快速返回首页。 假设你在一个很深的页面层级(比如首页->分类->商品列表->商品详情->订单确认->支付结果),想提供一个"一键回首页"的按钮。

    javascript 复制代码
    goHome() {
      // 获取页面栈
      const pages = getCurrentPages();
      // 如果栈长度大于1,说明不在首页,可以返回
      if (pages.length > 1) {
        // uni.reLaunch 会关闭所有页面,打开首页
        uni.reLaunch({
          url: '/pages/index/index'
        });
      } else {
        uni.showToast({
          title: '已经在首页了',
          icon: 'none'
        });
      }
    }
  • 场景2:跨页面直接通信。 从详情页返回列表页时,直接刷新列表页的数据。

    javascript 复制代码
    // 在详情页(Detail.vue)
    saveAndBack() {
      // 获取上一个页面(列表页)的实例
      const pages = getCurrentPages();
      const listPage = pages[pages.length - 2];
      // 调用列表页定义的刷新数据方法
      if (listPage && listPage.refreshList) {
        listPage.refreshList(); 
      }
      // 返回
      uni.navigateBack();
    }

注意 :直接通过页面实例操作其他页面的数据和方法虽然强大,但耦合性较高,需要你非常清楚页面栈的结构。在复杂的项目中,更推荐使用 Vuex(状态管理)全局事件总线(Global Event Bus) 来进行解耦的页面通信。


二、 路由跳转方式

uni-app 提供了5种核心的路由跳转API,它们对应着不同的页面栈操作和业务场景。选对了API,用户体验才能流畅自然。

方法 作用 页面栈变化 适用场景
uni.navigateTo 保留当前页面,跳转到新页面 Push新页面 最常用的跳转,如列表->详情
uni.redirectTo 关闭当前页面,跳转到新页面 Replace当前页面 中断当前流程,如登录页跳首页
uni.reLaunch 关闭所有页面,打开新页面 关闭所有旧页面,Open新页面 应用重启,如切换用户身份
uni.switchTab 跳转到 tabBar 页面 关闭所有非tabBar页面 切换底部导航
uni.navigateBack 返回上一页面或多步 Pop出一个或多个页面 返回上一级或首页

下面我们通过代码来详细讲述。

2.1 uni.navigateTo

这是你最常用的跳转方式。它会在页面栈中新增一个记录,原页面会被保留。

特点:

  • 新页面从右侧滑入屏幕。
  • 原页面保留在内存中,不会销毁。
  • 左上角自动出现"返回"箭头。

具体代码示例:

javascript 复制代码
// 在列表页(List.vue)中跳转到详情页(Detail.vue)
goToDetail(productId) {
  // 使用 uni.navigateTo 进行跳转
  uni.navigateTo({
    // 目标页面的路径,支持传递参数
    url: `/pages/detail/detail?id=${productId}&name=test`,
    // 跳转成功回调
    success: (res) => {
      console.log('跳转成功!', res);
    },
    // 跳转失败回调
    fail: (err) => {
      console.error('跳转失败:', err);
      uni.showToast({
        title: '跳转失败,请重试',
        icon: 'none'
      });
    },
    // 跳转结束的回调
    complete: () => {
      console.log('跳转动作完成,无论成功还是失败都会调用');
    }
  });
}

对应的页面栈变化过程图解:

flowchart TD Start[列表页 List] -->|执行
uni.navigateTo| Action[将详情页 Detail Push 入栈] Action --> Result[栈变为: Index, List, Detail] Result --> View[用户看到 Detail 页
List 被保留在栈中]

避坑navigateTo 只能用于跳转到非 tabBar 页面 。跳转tabBar页面请使用 uni.switchTab

2.2 uni.redirectTo

有时,你希望用户跳转到新页面后,不能再返回原页面。这时就需要 redirectTo。它用新页面替换当前页面,当前页面会被销毁。

特点:

  • 当前页面被关闭(出栈)。
  • 新页面在当前页的位置打开。
  • 左上角不会出现指向原页面的返回箭头。

具体代码示例:

javascript 复制代码
// 在 splash 页或登录页,应用启动后判断用户状态
onLoad() {
  // 检查用户是否已登录
  const isLoggedIn = checkLoginStatus(); // 假设的检查方法

  if (isLoggedIn) {
    // 如果已登录,直接重定向到首页,并且不能返回到这个splash页
    uni.redirectTo({
      url: '/pages/index/index'
    });
  } else {
    // 如果未登录,跳转到登录页
    uni.navigateTo({
      url: '/pages/login/login'
    });
  }
}

// 在登录页(Login.vue),登录成功后
handleLoginSuccess() {
  // 登录成功后,用首页替换掉登录页,用户无法再返回到登录页
  uni.redirectTo({
    url: '/pages/index/index'
  });
}

对应的页面栈变化:

  • 原栈:[Splash]
  • 执行 redirectTo(Home) 后,新栈:[Home] (Splash被替换掉了)

2.3 uni.reLaunch

这个API会关闭所有已打开的页面,然后打开一个新的页面。相当于重启了一次应用。

特点:

  • 所有页面栈都被清空
  • 然后打开指定的新页面。
  • 适用于需要完全重置导航状态的场景。

具体代码示例:

javascript 复制代码
// 场景1:在深页面路径中,提供"返回首页"功能,并重置应用状态
goHomeHard() {
  uni.reLaunch({
    url: '/pages/index/index'
  });
}

// 场景2:用户切换账号后,需要清空所有之前的页面状态,进入首页
afterSwitchAccount() {
  uni.reLaunch({
    url: '/pages/index/index'
  });
}

对应的页面栈变化:

  • 原栈:[Index, List, Detail, Cart, Order, Payment] (一个非常深的链条)
  • 执行 reLaunch(Home) 后,新栈:[Home] (所有旧页面全部被销毁)

2.4 uni.switchTab

用于跳转到 pages.json 中配置的 tabBar 页面,并关闭其他所有非 tabBar 页面

重要特性:

  • 跳转目标页面必须tabBar 中定义。
  • 跳转时,会清空页面栈中所有的非 tabBar 页面。
  • 在App端,点击 tabBar 或调用 switchTab,原 tabBar 页面的 onShow 会触发,但 onLoad 不会再次触发。

具体代码示例:

比方说我们的 pages.json 配置了首页(index)和个人中心(profile)两个tab。

json 复制代码
{
  "tabBar": {
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页"
      },
      {
        "pagePath": "pages/profile/profile",
        "text": "我的"
      }
    ]
  }
}
javascript 复制代码
// 在任何一个非tabBar页面(如商品详情页 Detail.vue)想切回首页
goToIndexTab() {
  uni.switchTab({
    url: '/pages/index/index' // 这个页面必须在 tabBar 的 list 中
  });
}

对应的页面栈变化:

  • 原栈:[Index (tab), List, Detail] (Index是tab页,但当前显示的是Detail)
  • 执行 switchTab(Index) 后,新栈:[Index (tab)] (List和Detail被全部关闭)

提示 :如果应用当前就在目标 tabBar 页面,再调用 switchTab 是不会触发任何页面变化的。

2.5 uni.navigateBack

用于返回上一页面或多级页面。它是唯一一个不指定目标url的导航API,因为它默认就是往回走。

核心参数:delta

  • delta: 表示返回的页面层数,默认为 1(返回上一页)。

具体代码示例:

javascript 复制代码
// 1. 最简单的返回上一页
goBack() {
  uni.navigateBack();
  // 相当于 uni.navigateBack({ delta: 1 });
}

// 2. 返回两级页面
// 假设页面栈是 [A, B, C],在C页面调用此方法,将直接返回到A页面
goBackTwoLevels() {
  uni.navigateBack({
    delta: 2
  });
}

// 3. 结合 getCurrentPages(),实现返回
// 比方说在分享进来的页面,如果只有一层,则返回时直接回到首页
smartBack() {
  const pages = getCurrentPages();
  if (pages.length === 1) {
    // 如果只有一页,说明是分享直链进来的,返回首页
    uni.switchTab({
      url: '/pages/index/index'
    });
  } else {
    // 否则正常返回
    uni.navigateBack();
  }
}

五种路由方式综合对比流程图:

flowchart TD Start[起始页面栈: A, B, C
当前页为 C] Start --> NavigateTo[uni.navigateTo
跳转到 D] NavigateTo --> ResultNT[新栈: A, B, C, D] Start --> RedirectTo[uni.redirectTo
用 D 替换 C] RedirectTo --> ResultRT[新栈: A, B, D] Start --> SwitchTab[uni.switchTab
跳转到 Tab页 T] SwitchTab --> ResultST[新栈: T
清空所有非Tab页] Start --> ReLaunch[uni.reLaunch
重启到新页 R] ReLaunch --> ResultRL[新栈: R
清空所有旧页] Start --> NavigateBack[uni.navigateBack
delta=1] NavigateBack --> ResultNB[新栈: A, B
C 被弹出]

三、 传参与接收参数

页面跳转往往不是孤立的,需要携带信息。比如从列表页跳转到详情页,必须告诉详情页:"你要展示哪个商品的ID"。

3.1 如何传递参数?

navigateTo, redirectTo 等方法的 url 中,可以像普通URL一样拼接参数。

具体示例如下:

javascript 复制代码
// 在列表页传递商品ID和名称
goToDetail(product) {
  uni.navigateTo({
    // ? 开始代表增加了参数,多个参数用 & 连接
    // 注意:参数值最好使用 encodeURIComponent 进行编码,防止特殊字符(如&)导致问题
    url: `/pages/detail/detail?id=${product.id}&name=${encodeURIComponent(product.name)}&type=physical`
  });
}

3.2 如何接收参数?

在目标页面的 onLoad 生命周期函数 中,可以接收到一个 options 对象,里面包含了所有传递过来的参数。

为什么是 onLoad 因为 onLoad 是页面首次加载时才会触发的生命周期。通过路由跳转并传递参数,对于目标页面来说就是一次"首次加载"。

具体代码如下:

javascript 复制代码
// 在详情页(Detail.vue)中
export default {
  data() {
    return {
      productId: '',
      productName: '',
      productType: ''
    };
  },
  onLoad(options) {
    // options 就是一个对象,包含了 url 中传递的所有参数
    console.log('接收到的参数:', options);

    // 将参数赋值给页面的 data,供模板或方法使用
    this.productId = options.id;
    this.productName = options.name; // 如果传递时编码了,这里可能需要 decodeURIComponent
    this.productType = options.type || 'digital'; // 设置默认值,防止未传参

    // 根据获取到的 id,去请求详细的商品数据
    this.fetchProductDetail(this.productId);
  },
  methods: {
    fetchProductDetail(id) {
      //根据 id 获取商品详情
      console.log(`开始请求商品ID为 ${id} 的详情数据...`);
    }
  }
};

一个完整的传参/接参流程:

sequenceDiagram participant L as 列表页(List.vue) participant D as 详情页(Detail.vue) L->>L: 用户点击商品,
触发 goToDetail 方法 L->>D: uni.navigateTo({
url: '/pages/detail/detail?id=123&name=Phone' }) Note over D: 页面初始化
触发 onLoad 生命周期 D->>D: onLoad(options) 执行
options = { id: '123', name: 'Phone' } D->>D: 将 options.id 赋值给
this.productId D->>D: 调用 this.fetchProductDetail('123')

特别注意

  1. URL长度限制 :传递大量数据(涉及复杂对象)时,不要通过URL参数传递,因为URL有长度限制。此时应该使用全局变量(如Vuex)本地存储(uni.setStorage)

  2. 参数类型 :通过URL传递的参数都是字符串类型 。如果需要数字、布尔值等,需要在接收端自行转换。

    javascript 复制代码
    onLoad(options) {
      this.productId = parseInt(options.id); // 转成数字
      this.isAvailable = options.available === 'true'; // 转成布尔值
    }
  3. 编码与解码 :对于可能包含特殊字符(如 &, =, ?, #, % 等)的参数值,在传递前使用 encodeURIComponent() 编码,接收后使用 decodeURIComponent() 解码,可以避免解析错误。


四、 导航栏自定义配置

导航栏提供了强大的配置能力,可以在 pages.json 中对其进行全局和页面的个性化设置。

4.1 全局配置与页面级配置

配置遵循"就近原则":页面级配置的优先级高于全局配置

pages.json 结构:

json 复制代码
{
  // 1. 全局配置 - 对所有页面生效
  "globalStyle": {
    "navigationBarTitleText": "我的默认App",     // 导航标题
    "navigationBarBackgroundColor": "#007AFF",  // 导航栏背景色
    "navigationBarTextStyle": "white",          // 标题颜色
    "backgroundColor": "#F8F8F8",               // 背景色
    "enablePullDownRefresh": false              // 是否开启下拉刷新
  },
  // 2. 页面路由列表
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "首页" 
      }
    },
    {
      "path": "pages/profile/profile",
      "style": {
        "navigationBarTitleText": "个人中心",
        "navigationBarBackgroundColor": "#4CD964", 
        "enablePullDownRefresh": true 
      }
    },
    {
      "path": "pages/detail/detail",
      "style": {
        "navigationBarTitleText": "商品详情",
        // 隐藏原生导航栏,实现全屏或自定义导航栏
        "navigationStyle": "custom"
      }
    }
  ],
  // 3. tabBar 配置
  "tabBar": {
    "color": "#7A7E83",
    "selectedColor": "#007AFF",
    "backgroundColor": "#FFFFFF",
    "list": [
      // tabBar列表 ...
    ]
  }
}

4.2 动态修改导航栏标题

很多时候,我们需要在页面加载后,根据数据动态设置标题。例如,在商品详情页,标题应该是商品的名字,这个名字来自后台接口。

核心API:uni.setNavigationBarTitle

代码示例:

javascript 复制代码
// 在详情页(Detail.vue)中
export default {
  onLoad(options) {
    this.productId = options.id;
    this.fetchProductDetail();
  },
  methods: {
    async fetchProductDetail() {
      // 模拟接口请求
      const res = await this.$api.getProductDetail(this.productId);
      if (res.success) {
        const product = res.data;
        // 动态设置导航栏标题为商品名称
        uni.setNavigationBarTitle({
          title: product.name // 从接口获取的商品名
        });
      }
    }
  }
};

4.3 自定义导航栏 ("navigationStyle": "custom")

当uni-app自带的导航栏样式无法满足你的设计需求时(比如需要加入搜索框、按钮、或者需要特殊的背景效果),你可以选择自定义导航栏

配置步骤:

  1. pages.json 中为指定页面启用自定义导航栏:

    json 复制代码
    {
      "path": "pages/my-custom-page/my-custom-page",
      "style": {
        "navigationStyle": "custom" 
      }
    }
  2. 在页面的 <template> 中,自己编写导航栏的UI结构:

    html 复制代码
    <template>
      <view>
        <!-- 自定义导航栏 -->
        <view class="custom-navbar">
          <!-- 状态栏占位,防止内容冲到状态栏下面 -->
          <view class="status-bar"></view>
          <!-- 导航栏内容区 -->
          <view class="navbar-content">
            <text class="nav-title">我的自定义标题</text>
            <button class="nav-btn">按钮</button>
          </view>
        </view>
        <!-- 页面内容,需要给自定义导航栏留出高度 -->
        <view class="page-content">
          ...
        </view>
      </view>
    </template>
  3. <style> 中编写样式,并处理好高度问题:

    css 复制代码
    <style scoped>
    /* 1. 状态栏高度占位 */
    .status-bar {
      height: var(--status-bar-height); 
      width: 100%;
    }
    
    /* 2. 自定义导航栏内容区 */
    .navbar-content {
      height: 44px; /* 导航栏标准高度 */
      background-color: #007AFF;
      display: flex;
      align-items: center;
      justify-content: center;
      position: relative;
      color: white;
    }
    
    /* 3. 页面内容需要有一个上边距 */
    .page-content {
      margin-top: calc(var(--status-bar-height) + 44px); /* 状态栏高度 + 导航栏高度 */
    }
    </style>

自定义导航栏的优缺点:

  • 优点:UI可高度自定义,实现任何复杂的导航栏效果。
  • 缺点
    1. 需要自己处理兼容性问题;
    2. 工作量增加,每个需要自定义的页面都要写一套结构样式;
    3. 在iOS上,滑动返回手势可能会与自定义导航栏中的按钮点击事件冲突,需要额外处理。

五、 总结

至此我们已经把uni-app路由导航的核心知识体系全部梳理完毕了。最后做一个整体总结,并提供一个综合小案例。

5.1 知识点

  1. 页面栈(Page Stack)

    • 本质:一个后进先出(LIFO)的栈结构,管理所有已打开的页面。
    • 核心APIgetCurrentPages(),用于获取当前栈实例,可进行跨页面通信和智能导航。
  2. 五大路由跳转方法

    • uni.navigateTo保留当前页,跳转新页。最常用。
    • uni.redirectTo关闭当前页 ,跳转新页。用于中断当前流程,不让返回。
    • uni.reLaunch关闭所有页 ,打开新页。用于重启应用状态
    • uni.switchTab跳转Tab页 ,关闭所有非Tab页。专为底部导航设计。
    • uni.navigateBack返回上一页或多页。最简单的返回操作。
  3. 参数传递与接收

    • 传递 :在跳转的 url 后通过 ?key=value&key2=value2 的形式拼接。
    • 接收 :在目标页面的 onLoad(options) 生命周期中,从 options 参数中获取。
    • 注意:参数是字符串,注意类型转换和特殊字符编码。
  4. 导航栏自定义

    • 静态配置 :在 pages.jsonglobalStyle 和每个页面的 style 中配置标题、颜色等。
    • 动态修改 :使用 uni.setNavigationBarTitle API。
    • 完全自定义 :设置 "navigationStyle": "custom",然后自己编写视图和样式,注意处理好状态栏高度。

5.2 最后,以一个简单的电商流程为例:

让我们用刚学的知识,模拟一个简单的电商页面跳转流程。以下只写核心思路代码,具体细节代码需要自行发挥!!!

javascript 复制代码
// 1. 首页 (index.vue) - 点击商品分类
goToCategory(categoryId) {
  uni.navigateTo({
    url: `/pages/category/category?id=${categoryId}`
  });
}

// 2. 分类页 (category.vue) - 接收分类ID,展示商品列表
onLoad(options) {
  this.categoryId = options.id;
  this.fetchGoodsList();
},
// 点击列表中的商品
onGoodsItemTap(goodsId) {
  uni.navigateTo({
    url: `/pages/goods-detail/goods-detail?goods_id=${goodsId}`
  });
}

// 3. 商品详情页 (goods-detail.vue) - 接收商品ID,展示详情
onLoad(options) {
  this.goodsId = options.goods_id;
  this.fetchGoodsDetail().then(goods => {
    // 动态设置导航栏标题为商品名
    uni.setNavigationBarTitle({ title: goods.name });
  });
},
// 点击加入购物车
addToCart() {
  uni.showToast({
    title: '添加成功'
  });
},
// 点击立即购买
buyNow() {
  // 跳转到订单确认页,并不允许返回到此详情页
  uni.redirectTo({
    url: `/pages/order-confirm/order-confirm?goods_id=${this.goodsId}`
  });
}

// 4. 订单确认页 (order-confirm.vue)
onLoad(options) {
  this.goodsId = options.goods_id;
},
// 提交订单成功
onOrderSubmitSuccess(orderId) {
  // 关闭所有页面,跳转到订单结果页
  uni.reLaunch({
    url: `/pages/order-result/order-result?order_id=${orderId}&status=success`
  });
}

// 5. 在订单结果页 (order-result.vue),提供"返回首页"的按钮
backToHome() {
  // 因为是用 reLaunch 跳过来的,栈里只有这一页,所以用 switchTab 回首页
  uni.switchTab({
    url: '/pages/index/index'
  });
}

结语

路由与导航,作为连接整个应用的脉络,其重要性不言而喻。理解页面栈的原理,能让你在遇到复杂的导航问题时游刃有余;熟练掌握五种跳转方式,能让你为用户设计出最符合直觉的交互流程; 希望这篇文章能够帮到你你,最后如果觉得文章写得还可以别忘了'一键三连'(点赞、关注、收藏),这是对我创作的最大鼓励!

有任何问题,欢迎在评论区留言,我们下篇见!

相关推荐
CSharp精选营2 小时前
ASP.NET Core Blazor进阶1:高级组件开发
前端·.net core·blazor
Sheldon一蓑烟雨任平生2 小时前
Vue3 组件库 Element Plus
vue.js·vue3·element plus·element ui·vue3 常用组件库
用户9714171814272 小时前
uniapp页面路由
vue.js·uni-app
Kingsaj2 小时前
uni-app打包app -- 在用户首次启动 App 时,强制弹出一个“用户协议与隐私政策”的确认对话框。
服务器·ubuntu·uni-app
Vue10242 小时前
uniapp 使用renderjs 封装 video-player 视频播放器, html5视频播放器-解决视频层级、覆盖、播放卡顿
uni-app·音视频·html5
用户90443816324602 小时前
AI 生成的 ES2024 代码 90% 有坑!3 个底层陷阱 + 避坑工具,项目 / 面试双救命
前端·面试
小p2 小时前
react学习6:受控组件
前端·react.js
黑云压城After2 小时前
纯css实现加载动画
服务器·前端·css
鹏多多2 小时前
Web使用natapp进行内网穿透和预览本地页面
前端·javascript