使用 Box 布局

用 Flexbox 按单元格构建仪表盘框架:顶栏、侧栏和卡片。

本章应用正在你的控制台中运行。按 ⌘⌥JCtrl+Shift+J⌘⌥KCtrl+Shift+K⌘⌥C 打开控制台(先开启开发者功能),然后试用。
观看本章3:39

本章内容

  • 顶部栏
  • 侧边栏和卡片
  • 默认支持响应式布局

控制台是由单元格组成的网格。Text.js 使用 Yoga 布局,它也是 React Native 使用的 flexbox 引擎,因此 <Box> 遵循 CSS flexbox 规则。尺寸以单元格为单位:p-1 表示一列和一行的内边距。

顶部栏

大多数界面采用纵向布局:先是一行高的顶部栏,再是其余内容。用 h-1 为顶部栏设置固定高度,用 grow 让内容占据剩余空间。

app/page.tsx+8-4tsx
移除:import { Box, Text, useInput } from "@textjs/app";新增:import { Box, Spacer, Text, useInput } from "@textjs/app";export default function Page() {  return (移除:    <Box className="flex-col border rounded px-2 py-1">移除:      <Text bold>▼ Acme Deploys</Text>移除:      <Text color="muted">Hello, console.</Text>新增:    <Box className="flex-col grow">新增:      <Box className="flex-row h-1 px-1 gap-2 shrink-0">新增:        <Text bold>▼ Acme</Text>新增:        <Text color="subtle">acme.local</Text>新增:        <Spacer />新增:      </Box>新增:      <Box className="flex-row grow">{/* sidebar + cards */}</Box>    </Box>  );}

<Spacer> 是一个可扩展的盒子:它后面的所有内容都会被推到右边缘。

添加一个带右边框的固定宽度侧边栏,以及三张平分剩余宽度的卡片。basis-0 配合 grow 可让每张卡片获得相同的宽度,不受内容影响。

app/page.tsx+31-1tsx
新增:const NAV = ["Overview", "Deployments", "Settings"];新增:新增:function Card({ title, value }: { title: string; value: string }) {新增:  return (新增:    <Box className="flex-col border rounded px-1 grow shrink basis-0" minWidth={14} minHeight={4}>新增:      <Text color="subtle">{title}</Text>新增:      <Text bold>{value}</Text>新增:    </Box>新增:  );新增:}新增:export default function Page() {新增:  const [sidebar, setSidebar] = useState(true);新增:  const [stacked, setStacked] = useState(false);新增:新增:  useInput((e) => {新增:    if (e.input === "s") setSidebar((v) => !v);新增:    if (e.input === "d") setStacked((v) => !v);新增:  });新增:  return (    <Box className="flex-col grow">      {/* top bar */}移除:      <Box className="flex-row grow">{/* sidebar + cards */}</Box>新增:      <Box className="flex-row grow">新增:        {sidebar && (新增:          <Box className="flex-col w-18 shrink-0 border-r px-1 pt-1">新增:            {NAV.map((item) => <Text key={item}>{item}</Text>)}新增:          </Box>新增:        )}新增:        <Box className={stacked ? "flex-col grow gap-1 p-1" : "flex-row grow items-start gap-1 p-1"}>新增:          <Card title="Production" value="acme-web" />新增:          <Card title="Deployments" value="6 today" />新增:          <Card title="Build time" value="38s p50" />新增:        </Box>新增:      </Box>    </Box>  );}

在控制台中按 s 和 d。Yoga 会重新计算布局,并且只重绘发生变化的行,因此切换侧边栏只需一次 console.log。

默认支持响应式布局

网格随停靠的 DevTools 面板调整大小。拖动控制台以增加宽度或高度,卡片就会重新排列。需要断点时,useBreakpoint() 会返回当前断点,以单元格为单位。

试用

这是本章结束时的 Acme Deploys,正在 DevTools 中运行。点击输入区,然后使用下列按键。

▼ 02 · 使用 Box 布局

打开控制台

⌘⌥J
CtrlShiftJ
⌘⌥K
CtrlShiftK
⌘⌥C

应用在 DevTools 中渲染。先在 Safari 设置 → 高级中开启“显示网页开发者功能”。 然后点击这里并按 s。

在桌面端打开

此应用在 DevTools 控制台中渲染,需要桌面浏览器。

测验

2 个问题

回答所有问题以完成本章。

className 工具类中的 p-1 表示什么?

 

哪个类能让盒子占据剩余空间?