Skip to content

响应式布局 ​

响应式设计应当顺应内容,而不是等比压缩。在开始搭界面之前,先思考各个区块在屏幕变窄时应当如何演变:某些辅助区域可以留下来并适当收缩;某些可以暂时收进按需展开的抽屉浮层中;而某些不关键的次要内容则可以直接隐藏。当三栏内容并排太挤时,应把次要的一栏收起或折叠,不要把文字和按钮压得变形。

页面外壳(AppShell)断点设置 ​

AppShell 的 mobileNav.breakpoint 决定了侧边导航栏(SideNav)在什么时候自动折叠进移动端抽屉里。默认的折叠断点是 md。

选项值触发宽度说明
sm640px仅在超小手机屏幕上折叠
md768px平板及以下屏幕折叠(默认推荐)
lg1024px小屏笔记本或横屏平板以下折叠
xl1280px普通桌面屏幕以下折叠
2xl1536px大屏幕以下折叠
none不收起始终保持左侧栏常驻,不使用移动端抽屉

当视口宽度小于所设断点时,原本常驻的左侧栏会移出主版面,转由汉堡按钮和呼出的抽屉来接管。同属于一个外壳内的顶栏也会复用这只抽屉,避免重复生成弹层。如果传入 :mobile-nav="false",则完全关闭移动端抽屉行为。

在 AppShell 内部的任何子组件里,你都可以随时调用 useAppShellMobile() 组合式函数,实时读取当前是否处于窄屏移动状态,以及抽屉是否正处于打开状态。

内容版心与布局(Layout) ​

Layout 负责把页面的布局结构清晰切分为:页眉(header)、起始侧(start)、主要内容(content)、结束侧(end)和页脚(footer)等插槽。

  • 舒适阅读宽度:通常一行正文文本在 40 到 60 个中文字符(或 60 到 80 个英文字符)时人眼读起来最不容易疲劳。Layout 提供了 contentWidth 属性(单位是像素),能方便地限制中间正文栏的宽度,同时保持上下的分隔线横向拉通铺满,无需在每个段落里层层包裹容器。
  • 自适应侧面板:放在结束插槽(end slot)里的 LayoutPanel 经常用来展示选中的条目详情。当屏幕变窄空间不够时,可以借助条件渲染在窄屏时隐藏它,改为需要时通过弹窗或底部抽屉查看。
vue
<script setup lang="ts">
import { useMediaQuery } from '@astryx-vue/core'
import { AppShell } from '@astryx-vue/core/AppShell'
import { Layout, LayoutContent, LayoutPanel } from '@astryx-vue/core/Layout'
import { SideNav, SideNavItem } from '@astryx-vue/core/SideNav'

// 监听屏幕是否小于 1024px
const isNarrow = useMediaQuery('(max-width: 1024px)')
</script>

<template>
  <AppShell :mobile-nav="{ breakpoint: 'md' }">
    <template #sideNav>
      <SideNav>
        <SideNavItem href="/orders" label="订单" />
      </SideNav>
    </template>

    <Layout :content-width="720">
      <LayoutContent>
        <p>订单列表</p>
      </LayoutContent>

      <!-- 仅在宽屏展示右侧面板,窄屏时隐藏以保证阅读体验 -->
      <template v-if="!isNarrow" #end>
        <LayoutPanel :width="380" has-divider>
          <p>订单详情</p>
        </LayoutPanel>
      </template>
    </Layout>
  </AppShell>
</template>

在这个例子里:

  1. 当屏幕宽于 1024px 时,呈现三栏结构:侧导航、正文、380px 的右侧面板;
  2. 宽度小于 1024px 时,右侧面板隐藏,腾出完整空间显示正文;需要看详情时可通过 Dialog 或 BottomSheet 调出;
  3. 进一步变窄到 md(768px)以下时,侧导航自动收录到移动端抽屉里。

useMediaQuery 在组件 setup 初始化时就会同步计算一次状态,并在窗口缩放时平滑响应。

自动换行的网格布局(Grid) ​

Grid 组件的 columns 属性如果直接写成固定的数字,例如 :columns="7",那么即便在屏幕极窄的手机上,它也依旧会死板地强行挤成 7 列(适合用来做固定星期的日历排版)。

如果你希望网格能根据容器宽度自动增减列数,可以传入 { minWidth, max } 配置对象:

  • minWidth:每列最小允许的宽度(像素);
  • max:最多允许排成多少列。

容器放不下更多列时会自动少一列,并把剩余卡片顺延换行;当缩窄到只剩一列时,卡片宽度会自动伸展填满整个容器。gap 属性设置的卡片间隙,也会被精准计算进列宽的容量判断中。

vue
<!-- 宽屏时最多 4 列,屏幕变窄时自动减少列数换行 -->
<Grid :columns="{ minWidth: 240, max: 4 }" :gap="3">
  <!-- 卡片内容 -->
</Grid>

<!-- 一周 7 天的日历视图,每一档宽度都保持固定的 7 列 -->
<Grid :columns="7" :gap="1">
  <!-- 日期内容 -->
</Grid>

此外,你还可以通过 repeat 属性控制未填满时的排版策略:

  • repeat="fill"(默认值):保留空列占位,确保每一列的卡片都保持相同宽度。
  • repeat="fit":收起多余的空列,让已有的卡片均分并撑满整行空间。