vue2实现【瀑布流布局】

瀑布流

    • [1. 解释](#1. 解释)
    • [2. 形成结构和样式](#2. 形成结构和样式)
    • [3. 自定义指令](#3. 自定义指令)

1. 解释

  • 瀑布流特征:
  1. 等宽不等高:元素宽度固定,高度根据内容自适应。
  2. 错落排列:元素像瀑布一样从上到下依次填充,自动寻找最短列插入

体现:图中第一排1,2,3元素中,3是最短高度,就是该行最短列。

2. 形成结构和样式

html 复制代码
<template>
  <div class="page-main">
    <div class="card">
      <!-- v-waterfall是自定义指令 属性值是个回调函数-->
      <div v-waterfall="el => updateLayout(el)" class="card-item" v-for="item in cardDate" :key="item.id"
        :style="{ background: item.color, height: item.height }">
        <p class="text">{{ item.id }}</p>
      </div>
    </div>
  </div>
</template>
javascript 复制代码
//这是<script>data中的数据,结构是通过v-for遍历的
 cardDate: [
        { id: 1, color: '#76da6e', height: '100px' },
        { id: 2, color: '#57c797', height: '80px' },
        { id: 3, color: '#54cac7', height: '70px' },
        { id: 4, color: '#b16dc7', height: '120px' },
        { id: 5, color: '#dc933d', height: '130px' },
        { id: 6, color: '#b74acf', height: '90px' },
        { id: 7, color: '#d93e5a', height: '80px' },
        { id: 8, color: '#5474dd', height: '100px' },
        { id: 9, color: '#e42526', height: '120px' },
        { id: 10, color: '#e86c92', height: '90px' }
      ],
css 复制代码
<style scoped>
/* .page-main {
  position: relative;
} */

.card {
  position: relative;
  margin: 0 auto;
  width: calc(3 * 200px);
  /* 3列,每列200px宽度*/
}

.card-item {
  /* 相对于最近的非static定位的祖先元素(.card)定位(0,0) */
  position: absolute;
  width: 200px;

  /* 使得内容居中(可省略) */
  display: flex;
  align-items: center;
  justify-content: center;

  color: black;
  font-size: 24px;
  /* 监听到css样式变化,过渡0.3s效果 */
  transition: all 0.3s;
}
</style>

未加上js动态计算每个元素的位置---初始样子是将所有元素重叠在一起(如图)

然后就要计算出每块元素应该存在的位置(top和left)【css中每块元素position都是absolute,而且没有设置边偏移,默认都是0】

DOM元素尺寸属性不了解可以看这里有图文说明

javascript 复制代码
<script>
export default {
  name: 'App',
  data() {
    return {
      cardDate: [
        { id: 1, color: '#76da6e', height: '100px' },
        { id: 2, color: '#57c797', height: '80px' },
        { id: 3, color: '#54cac7', height: '70px' },
        { id: 4, color: '#b16dc7', height: '120px' },
        { id: 5, color: '#dc933d', height: '130px' },
        { id: 6, color: '#b74acf', height: '90px' },
        { id: 7, color: '#d93e5a', height: '80px' },
        { id: 8, color: '#5474dd', height: '100px' },
        { id: 9, color: '#e42526', height: '120px' },
        { id: 10, color: '#e86c92', height: '90px' }
      ],
      columnHeights: [0, 0, 0] //每列元素的高度
    }
  },
  directives: {
    waterfall: {
      inserted(el, binding) {
        const callback = binding.value || {};
        callback(el);
      }
    }
  },
  methods: {
    updateLayout(item) {
      const column = this.getMinColumnHeight(this.columnHeights);

      //计算每个元素位移x轴和y轴距离
      const itemTop = this.columnHeights[column];
      const itemLeft = column * item.clientWidth;
      item.style.transform = `translate(${itemLeft}px,${itemTop}px)`;
      //此时该元素item已经定位完成
      //则重新跟新原本最短列为this.columnHeights[column] + item.offsetHeight; 
      this.columnHeights[column] += item.offsetHeight;
    },
    getMinColumnHeight(arr) {
      let min = Math.min(...arr);
      return arr.indexOf(min) != -1 ? arr.indexOf(min) : 0;
    }
  },
}
</script>

3. 自定义指令

javascript 复制代码
directives: {
    waterfall: {
      inserted(el, binding) {
        console.log(binding);
        const callback = binding.value || {};
        callback(el);
      }
    }
  },

el则是每个cart-item元素

(注:本文例子参考这个b站视频,我进行了补充)

相关推荐
环境栈笔记30 分钟前
指纹浏览器 WebRTC 怎么设置?从 ICE 候选、代理出口到功能验证
前端·人工智能·后端·自动化
赵大仁1 小时前
官网性能优化实战:LCP 3.2s → 2.1s、CLS 0.107 → 0,以及被我推翻的 6 个判断
前端·性能优化·cls·lcp·core web vitals
xiancai_xianyu1 小时前
Text2SQL落地生产库前,SQL要过哪三道闸
前端·数据库·sql·sql注入·text2sql·ai agent开发·企业级ai框架
小羊没烦恼!1 小时前
T-SQL查询进阶--理解SQL SERVER中的分区表
服务器·开发语言·前端·javascript·html
史瓦辛格1 小时前
给 DeepSeek Harness 写费用插件:把「这次会话花了多少钱」算准
前端·deepseek
星光不问赶路人1 小时前
Vue 3 + TypeScript 中 enum 的使用实践
前端·vue.js
鸥梨菌Honevid1 小时前
UVM 中 REQ 和 RSP 类型详解:从通信模型到 item_done 与 put_response
java·前端·servlet
IT_陈寒2 小时前
Python多进程共享变量这个坑,差点让我加班到凌晨
前端·人工智能·后端
鸿蒙开发2 小时前
PDF 盖黑框不等于脱敏:用 PDF.js + Canvas + pdf-lib 实现永久遮盖
前端·react.js
xixingzhe22 小时前
Nginx 看懂请求耗时瓶颈
服务器·前端·nginx