vue 瀑布流组件实现

最近项目要实现一个瀑布流布局,结合网上的案例以及自己的理解实现了一版,特在此记录一下,有兴趣的同学欢迎一起探讨交流学习  (第一次写这种东西~~~),废话不多说,开整!!!!!

先上张图!!!

5835191395c44241a6163f364e99cda3.jpeg

【必看】原理:

       说一下我对瀑布流布局原理的理解,如上图,实现这种布局方式,主要有绝对定位方式 以及两列布局方式,原理都是通过判断每列高度差来做,重新处理数据,动态获取每列元素盒子高度,每次往盒子高度小的那列push数据,绝对定位方式,通过找到最小高度的列,设置元素的 left top值来做,但是这种方式有个缺点是,由于子元素绝对定位导致父元素高度塌陷,如果我们需要获取父元素高度做一些事情的话,可能不太好处理,所以我这里使用 float 两列布局(两列是一个概数,当然你可以设置5  6  7 8 列)

步骤一:

html  css 直接上代码

<template>
  <!-- 运用float 布局,多列数组方式,如果用绝对定位布局,会使父元素高度塌陷,使用不方便 -->
	<div class="waterfall clearfix">
		<div class="list" v-for="(columnList,i) in newList" :key="i" ref="waterfall">
      <slot name="content" :item="columnList"></slot>
    </div>
	</div>
</template>


<style scoped lang="less">
.waterfall {
  .list {
    float: left;
    &:last-child {
      margin-right: 0 !important;
    }
  }
}

.clearfix::after{
  content:'';
  display:block;
  clear:both;
}
</style>

步骤二:

样式处理好了后,就该我们处理数据了

首先加载瀑布流组件的时候,动态创建二维数组,并且给每列数组添加一条数据,(我觉得这样好理解,每列里有了数据,也就能获取到每列的dom元素,也就能获取到高度差)

export default {
	name: 'waterfall',
	props: {
    list: {
      type: Array,
      default: []
    },
    marginRight: {
      type: Number,
      default: '0'
    }
  },
  data() {
    return {
      column: 2,
      newList: [],
    }
  },
  created() {
    // 循环列数,给每一列先添加一条数据,那两列就有高度了,也能利用高度差进行判断
    if(this.list.length > 1) {
      for(let i = 0; i< this.column;i++) {
        // 此处需要用$set 创建二维数组
        this.$set(this.newList,i,[])
        this.newList[i][0] = this.list.shift()
      }
    }else {
      this.$set(this.newList,0,[])
      this.newList[0][0] = this.list.shift()
    }
    
  },
}

步骤三:

处理父组件传过来的数据,动态的push到两列数组中

init() {
      let domHeight = [] // 存放高度得数组
      let waterfallDom = this.$refs.waterfall

      waterfallDom.forEach((item)=>{
        domHeight.push(item.offsetHeight)
        item.style.marginRight = this.marginRight
      })
      let minHeight = Math.min(...domHeight); // 获取到最小高度
      let index = domHeight.findIndex(item => item === minHeight) // 获取到最小高度得下标
      if(this.list.length) {
        // 给最小高度得数组里添加数据
        this.newList[index].push(this.list.shift())
      }
    }

步骤四:

每次调用步骤三中的方法 动态的处理父组件传过来的数据,我这里用的监听

watch: {
    // 这里要用 $nextTick 元素渲染完成 再次调用方法重新获取高度 push数据
    list(val) {
      console.log(val,'增加了嘛');
      this.$nextTick(()=>{
        this.init()
      })
    }
  },

完结:撒花!!!

奥! 完整代码附上!ps:这里没有处理图片,瀑布流最重要的是图片高度的自适应,由于图片加载有延迟,影响获取dom元素的高度,所以最完美的是服务端把图片高度返回,提前设置子元素图片高度占位,这样就完美了!!!!(完整代码组件可以直接拿来使用)

<waterfall :list="item.items" marginRight="9px">
   <template  #content="list">
      <goods :obj="val" v-for="(val,s) in list.item" :key="s" ></goods>
   </template>
</waterfall>
<template>
  <!-- 运用float 布局,多列数组方式,如果用绝对定位布局,会使父元素高度塌陷,使用不方便 -->
	<div class="waterfall clearfix">
		<div class="list" v-for="(columnList,i) in newList" :key="i" ref="waterfall">
      <slot name="content" :item="columnList"></slot>
    </div>
	</div>
</template>

<script>
export default {
	name: 'waterfall',
	props: {
    list: {
      type: Array,
      default: []
    },
    marginRight: {
      type: Number,
      default: '0'
    }
  },
  data() {
    return {
      column: 2,
      newList: [],
    }
  },
  created() {
    // 循环列数,给每一列先添加一条数据,那两列就有高度了,也能利用高度差进行判断
    // 这里写的不好,有需要的同学自己优化吧
    if(this.list.length > 1) {
      for(let i = 0; i< this.column;i++) {
        // 此处需要用$set 创建二维数组
        this.$set(this.newList,i,[])
        this.newList[i][0] = this.list.shift()
      }
    }else {
      this.$set(this.newList,0,[])
      this.newList[0][0] = this.list.shift()
    }
    
  },
  watch: {
    // 这里要用 $nextTick 元素渲染完成 再次调用方法重新获取高度 push数据
    list(val) {
      // console.log(val,'增加了嘛');
      this.$nextTick(()=>{
        this.init()
      })
    }
  },
	methods: {
		init() {
      let domHeight = [] // 存放高度得数组
      let waterfallDom = this.$refs.waterfall

      waterfallDom.forEach((item)=>{
        domHeight.push(item.offsetHeight)
        item.style.marginRight = this.marginRight / 3.75+ 'vw'
      })
      let minHeight = Math.min(...domHeight); // 获取到最小高度
      let index = domHeight.findIndex(item => item === minHeight) // 获取到最小高度得下标
      if(this.list.length) {
        // 给最小高度得数组里添加数据
        this.newList[index].push(this.list.shift())
      }
    }
	}
}
</script>

<style scoped lang="less">
.waterfall {
  .list {
    float: left;
    margin-right: 9px;
    &:last-child {
      margin-right: 0 !important;
    }
  }
}

.clearfix::after{
  content:'';
  display:block;
  clear:both;
}
</style>

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 要实现一个 Vue 3 瀑布流组件,你可以这么做: 1. 在你的 Vue 项目中安装并引入 masonry 布局插件,比如: ``` npm install masonry-layout ``` 2. 在你的 Vue 组件中引入 masonry 布局插件,并在 mounted 钩子函数中初始化 masonry 布局: ``` import Masonry from 'masonry-layout'; export default { mounted() { this.msnry = new Masonry(this.$el, { // 配置 masonry 布局的选项 }); }, }; ``` 3. 在组件的 template 中使用 masonry 布局。你可以在外层包裹一个容器元素,然后给容器元素的子元素设置类似 masonry-brick 的类名,这些子元素就会按照 masonry 布局的方式排列: ``` <template> <div class="masonry-container"> <div class="masonry-brick" v-for="item in items" :key="item.id"> <!-- 这里是单个瀑布流元素的内容 --> </div> </div> </template> ``` 4. 在组件的 data 中定义 items 数据,表示瀑布流中的所有元素,然后在 template 中使用 v-for 指令渲染这些元素。 5. 如果你想在组件中动态添加、删除瀑布流元素,你可以在对应的方法中调用 masonry 布局插件的 addItems、remove、reloadItems 等方法来更新布局。 例如,在组件的 addItem 方法中,你可以这么写: ``` addItem() { // ### 回答2: 要实现一个基于Vue3的瀑布流组件,我们可以按照以下步骤进行: 1. 创建一个Vue组件,并在组件中定义我们需要的数据和方法。 2. 在数据中定义一个数组,用于存储需要展示的图片或其他内容的信息,例如图片的URL地址。 3. 在组件的生命周期钩子函数中,可以使用一些异步请求或者模拟数据的方法来获取图片或其他内容的信息,并将获取到的数据存储到数组中。 4. 在组件的模板中,使用`v-for`指令来循环遍历数组中的数据,并在每个循环项中展示相应的内容。 5. 使用CSS样式来实现瀑布流布局,可以使用`grid`布局或者`flex`布局来实现。设置每个项的宽度和高度,并使用`column-count`或者`column-width`等属性来控制列数和列宽。 6. 当内容很多时,需要实现视图滚动时的无限加载功能,可以通过监听页面的滚动事件,在滚动到底部时加载更多的内容。 7. 可以添加一些交互的功能,例如点击某个内容项时,可以弹出大图展示或者跳转到详情页。 总结起来,实现一个Vue3的瀑布流组件主要需要定义数据、实现数据的获取和展示,以及使用CSS样式来布局和滚动加载等功能。通过以上步骤的操作,我们就可以完成一个基于Vue3的瀑布流组件。 ### 回答3: 实现一个Vue3瀑布流组件可以通过以下步骤进行: 1. 安装Vue3和相关依赖:首先,我们需要在项目中安装Vue3和其他可能用到的相关依赖,可以使用npm或yarn命令进行安装。 2. 创建瀑布流组件:在Vue3中,创建一个组件需要使用`createApp`方法。我们可以在需要显示瀑布流的页面上使用`createApp`方法创建一个Vue实例,并在`setup`函数中定义瀑布流组件。 3. 定义瀑布流布局:在瀑布流组件中,我们需要定义如何进行布局。一种常见的瀑布流布局是使用CSS的`column-count`属性实现。我们可以在瀑布流组件的模板中使用`v-for`指令遍历需要展示的数据,并使用`column-count`属性将它们分成多列。 4. 动态计算布局:由于瀑布流中的每列高度不一致,我们需要动态计算每个元素的位置。可以在瀑布流组件的`setup`函数中使用Vue3的响应式数据来保存每列的高度,并在模板中根据每列的高度动态设置每个元素的位置。 5. 处理滚动加载:瀑布流一般需要滚动加载更多数据,我们可以通过监听滚动事件来判断是否需要加载更多数据。可以使用Vue3的`onMounted`钩子函数来在组件加载完毕后绑定滚动事件,并使用`onUnmounted`钩子函数在组件卸载时解绑滚动事件。 6. 实现数据加载:在滚动加载时,可以通过请求接口或其他方式加载更多数据,并将新加载的数据添加到原有的数据列表中。可以在瀑布流组件的`setup`函数中使用Vue3的响应式数据来保存数据列表,并在模板中使用`v-for`指令遍历展示所有的数据。 7. 响应式优化:为了提高性能和用户体验,可以对瀑布流组件进行响应式优化。可以使用Vue3的`watchEffect`函数来监听数据的变化,并在数据发生变化时重新计算布局和渲染页面。 总结:通过以上步骤,我们可以实现一个基本的Vue3瀑布流组件。当然,实际项目中可能还需要考虑更多的功能和细节,如图片加载优化、动画效果等。希望以上的回答能给您提供一些参考。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值