根部视图

跨页面共享应用级壳层及状态

小程序侧本身没有“根部视图”这一层概念,但在真实项目里,总会有一部分 UI 和状态需要全局共享。

Oiyo 把 src/App.vue 定义成根部视图,让你能用更接近 Web 应用的方式组织:

  • 全局壳层(比如全局背景、全局弹窗承载点、统一的布局容器)
  • 根上下文(全局状态/方法的统一落点)

根部视图可以理解为一个“全局容器”:它比页面更早、更稳定,适合承载跨页面都需要的内容。

机制概览

在 Oiyo 中,src/App.vue 通常同时扮演三件事:

  • 页面插槽:<OiyoPage /> 标记当前路由页面渲染位置
  • 全局壳层:每个页面都会复用的 UI(背景、全局弹窗承载点等)
  • 可选的全局能力入口:布局容器 <OiyoLayout>、根上下文 defineRootContext()

下面只解释“它是怎么工作的”,具体如何落代码请看使用指南。

页面插槽(<OiyoPage />

<OiyoPage /> 的语义是“把当前路由匹配到的页面渲染在这里”。它不是普通组件替身,而是框架路由渲染的插槽。

形状示意(强调它是路由插槽,而不是页面组件本身):

<template>
  <OiyoPage />
</template>
src/App.vue<template> 里必须包含 <OiyoPage />(或 <oiyo-page />),否则应用无法正常渲染路由页面。

全局壳层

全局壳层指“无论进入哪个页面都存在”的 UI 与承载点,例如:统一背景、全局弹窗/Toast 容器、全局蒙层等。

它的原则是:放“所有页面都共享”的内容,不放“只属于某个页面”的差异。

布局入口(<OiyoLayout />

布局系统的关键不是“怎么写布局文件”,而是“渲染链路”:App.vue 提供一个布局容器入口,布局组件再通过 <slot /> 包裹页面内容。

布局的命名、默认布局选择等规则见布局概念页。

布局系统:渲染链路、默认与具名布局、布局名解析

根上下文(defineRootContext)

根上下文用于组织“跨页面共享”的状态与方法。它的价值是统一落点与生命周期,而不是强行把所有状态集中到一个文件。

形状示意(强调返回值是“全局可复用的一组能力”):

const ctx = defineRootContext(() => {
  return {
    // user, token, logout, openGlobalModal...
  }
})

如果某段状态只服务单页或强依赖某个业务模块,把它放在页面或 composables 往往更清晰。

根上下文是“组织方式”,不是强行把所有状态塞到一个地方。可以从最需要共享的一两个字段开始。

形状示意

下面是根部视图常见的“结构关系”示意(强调插槽与入口点,而不是可照抄的业务模板):

src/App.vue
<script setup lang="ts">
// 可选:声明跨页面共享上下文(字段与类型以 API 参考为准)
// defineRootContext(() => ({ ... }))
</script>

<template>
  <!-- 可选:启用布局渲染入口 -->
  <!-- <OiyoLayout> -->
  <OiyoPage />
  <!-- </OiyoLayout> -->
</template>

适合放什么

  • 登录态/用户信息
  • 全局开关(feature flag)
  • 全局弹窗/Toast 的统一控制方法

不适合放什么

  • 只服务单个页面的局部状态
  • 强依赖某个业务模块的状态(更适合放在页面或 composables 内)

延伸阅读

了解如何在 App.vue 中设置全局壳层和跨页面的状态
尝试如何在应用中新增一个页面
App.vue 文件在工程结构中的职责与边界(结构视角)