宫格布局的标配方案
App 首页的「金刚区」、个人中心的功能入口、九宫格抽奖面板,背后都是同一个布局模型——宫格。Vant 的 Grid 组件用一行配置搞定均分列数、间距、边框和正方形格子,不需要手写任何 flex 计算。
最简示例
html
demo.vue
<template>
<van-grid :column-num="4" :gutter="10">
<van-grid-item
v-for="item in menus"
:key="item.text"
:icon="item.icon"
:text="item.text"
@click="onGo(item)"
/>
</van-grid>
</template>
<script setup>
import { ref } from "vue";
import { showToast } from "vant";
const menus = ref([
{ icon: "wap-nav", text: "分类" },
{ icon: "search", text: "搜索" },
{ icon: "cart-o", text: "购物车" },
{ icon: "user-o", text: "我的" },
]);
const onGo = (item) => showToast(item.text);
</script>
内置图标
icon 属性直接填 Vant 内置图标名(如 wap-nav、cart-o),完整清单见官方图标库页面。
常用属性详解
column-num:控制列数
默认 4 列,改成 3 列或 5 列都只是改一个数字,格子自动均分剩余宽度:
html
demo.vue
<!-- 3 列大图标入口 -->
<van-grid :column-num="3">...</van-grid>
<!-- 5 列紧凑金刚区 -->
<van-grid :column-num="5" :border="false">...</van-grid>
square 与 gutter
square 让格子保持正方形(宽高相等),gutter 控制格子间距,两者常搭配使用:
html
demo.vue
<!-- 正方形格子 + 8px 间距 + 无边框,类似相册九宫格 -->
<van-grid :column-num="3" square :gutter="8" :border="false">
<van-grid-item v-for="img in photos" :key="img">
<img :src="img" class="photo" />
</van-grid-item>
</van-grid>
badge 角标
格子内容需要小红点或数字角标时,用 badge 属性:
html
demo.vue
<van-grid :column-num="4">
<van-grid-item icon="chat-o" text="消息" :badge="unread > 99 ? '99+' : unread" />
<van-grid-item icon="star-o" text="收藏" dot />
<van-grid-item icon="setting-o" text="设置" />
<van-grid-item icon="service-o" text="客服" />
</van-grid>
<script setup>
import { ref } from "vue";
const unread = ref(128);
</script>
自定义格子内容
默认的「图标 + 文字」满足不了设计稿时,用默认插槽塞任意内容,此时格子只负责布局:
html
wallet.vue
<template>
<van-grid :column-num="3" :border="false">
<van-grid-item v-for="item in wallet" :key="item.label">
<div class="stat">
<span class="stat-num">{{ item.value }}</span>
<span class="stat-label">{{ item.label }}</span>
</div>
</van-grid-item>
</van-grid>
</template>
<script setup>
import { ref } from "vue";
const wallet = ref([
{ value: "12", label: "优惠券" },
{ value: "328.50", label: "余额(元)" },
{ value: "6", label: "积分" },
]);
</script>
<style scoped>
.stat { display: flex; flex-direction: column; align-items: center; }
.stat-num { font-size: 18px; font-weight: 600; color: #323233; }
.stat-label { font-size: 12px; color: #969799; margin-top: 4px; }
</style>
icon 插槽:图形不限于图标
只想换图标、保留文字排版时,用 icon 插槽放图片或自定义 SVG:
html
demo.vue
<van-grid-item v-for="item in entries" :key="item.text" :text="item.text">
<template #icon>
<img :src="item.img" class="entry-img" />
</template>
</van-grid-item>
跳转路由
GridItem 内置路由能力,to 属性等价于 router.push,还可配 replace:
html
demo.vue
<van-grid :column-num="4">
<van-grid-item icon="orders-o" text="订单" to="/order/list" />
<van-grid-item icon="location-o" text="地址" :to="{ name: 'address' }" />
<van-grid-item icon="coupon-o" text="卡券" to="/coupon" replace />
<van-grid-item icon="question-o" text="帮助" url="https://help.example.com" />
</van-grid>
属性速查表
| 属性(Grid) | 类型 | 默认值 | 说明 |
|---|---|---|---|
| column-num | number / string | 4 | 列数 |
| icon-size | number / string | 28px | 图标大小 |
| gutter | number / string | 0 | 格子间距 |
| border | boolean | true | 是否显示边框(gutter > 0 时自动关闭) |
| square | boolean | false | 是否固定为正方形 |
| reverse | boolean | false | 是否调换图标与文字位置 |
| clickable | boolean | false | 是否开启点击反馈 |
| 属性(GridItem) | 说明 |
|---|---|
| text | 文字内容 |
| icon / badge / dot | 图标、角标数字、小红点 |
| to / url / replace | 路由跳转 / 页面链接 / 是否无痕跳转 |
踩坑记录
gutter 大于 0 时格子间不再共享边框,border 会被强制关闭;想要"有间距又有边框"只能自定义内容自己画边框。
💡 小技巧:内容溢出导致格子高度不一致时,给格子内容套一层固定高度的容器,或直接开 square,视觉立即对齐。
总结
Grid 组件的定位是「布局 + 角标 + 路由」三合一:常规入口用属性即可零样式完成,复杂内容交给插槽。记住 column-num / square / gutter 这三板斧,90% 的宫格需求都能在十分钟内落地。
好的组件库不是功能多,而是让常见需求变得不值得写 CSS。