优雅的 Vue 瀑布流方案

优雅的 Vue 瀑布流方案

在处理高度不一的卡片(如图片流、资源列表)时,传统的栅格系统(Grid)或 Flex 布局往往会因为一行中最高的那张卡片,导致同行其他卡片下方出现大量死白区域。

瀑布流(Masonry Layout) 的核心在于“缝隙填充”:它会优先寻找高度最短的那一列进行插入。只要卡片分布合理,整个页面会呈现出紧凑、错落有致的视觉效果,非常适合资源分享类站点。

避坑指南:版本与安装

在 Vue 生态中,做瀑布流首推 vue-masonry-wall。但请注意,根据你的 Vue 版本,安装包是不一样的:

  • Vue 3 项目: 请务必安装 @yeger/vue-masonry-wall(这是目前维护最频繁、兼容性最好的版本)。

  • Vue 2 项目: 请使用旧版的 vue-masonry-wall

如果你在 Vue 3 中错误使用了旧包,会遇到明显的 API 兼容性报错。建议统一使用 pnpm 或 npm 安装最新版:

Bash

# Vue 3 推荐安装命令 
pnpm add @yeger/vue-masonry-wall 
# 或者
npm install @yeger/vue-masonry-wall

核心实现

1. 全局注册 (main.js)

在 Vue 3 中,我们需要在初始化 App 时通过 .use() 插件化引入:

import { createApp } from "vue";
import MasonryWall from "@yeger/vue-masonry-wall";
import App from "./App.vue";

const app = createApp(App);
app.use(MasonryWall);
app.mount("#app");

 

2. 组件内实战

资深笔者提示: 当数据量突破百条时,DOM 渲染压力会陡增。务必配合分页加载无限滚动来优化前端性能。

代码段
<template>
  <masonry-wall :items="items" :column-width="300" :gap="16">
    <template #default="{ item, index }">
      <div class="item-card">
        <img :src="item.image" :alt="item.title" loading="lazy" />
        <div class="content">
          <h3>{{ item.title }}</h3>
          <p>{{ item.description }}</p>
        </div>
      </div>
    </template>
  </masonry-wall>
</template>

<script setup>
import { ref } from "vue";

const items = ref([
  { id: 1, title: "精选源码", description: "高质量 Vue 项目模板", image: "https://api.test.com/img1.jpg" },
  // ... 更多模拟数据
]);
</script>

<style scoped>
.item-card {
  background: #ffffff;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  transition: transform 0.3s ease;
}
.item-card:hover {
  transform: translateY(-5px);
}
.item-card img {
  width: 100%;
  display: block; /* 消除图片底部间隙 */
  object-fit: cover;
}
.content {
  padding: 12px;
}
</style>

 

进阶:如何科学地处理响应式?

原稿中直接在 computed 里读取 window.innerWidth 是一个常见误区,因为 window 对象不是响应式的,窗口变大小时布局并不会自动重算。

更稳妥的做法是: 利用该组件自带的响应式特性。其实 column-width 本身就支持动态计算。如果你追求极致,可以使用 VueUse 库中的 useWindowSize,或者像下面这样简单处理:

代码段
<script setup>
import { ref, onMounted, onUnmounted } from "vue";

const columnWidth = ref(300);

const updateWidth = () => {
  const width = window.innerWidth;
  if (width < 640) columnWidth.value = 160;      // 手机端
  else if (width < 1024) columnWidth.value = 240; // 平板
  else columnWidth.value = 300;                  // PC端
};

onMounted(() => {
  updateWidth();
  window.addEventListener('resize', updateWidth);
});

onUnmounted(() => {
  window.removeEventListener('resize', updateWidth);
});
</script>

 

配置项详解

参数 类型 说明
items Array 必须。循环渲染的数据源。
column-width Number 每一列的最小宽度,组件会根据此值自动分配列数。
gap Number 卡片之间的间距(像素)。
ssr-columns Number 在服务端渲染阶段预设的列数,防止首屏跳动。

结语: masonry-wall 胜在轻量且不需要复杂的计算逻辑,对于个人资源站或小型社区论坛来说,是性价比最高的布局方案。

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容