vue使用列表渲染 实现瀑布流布局

最近一个vue项目需要瀑布流布局,最终结合自己的需求使用了vuev-for实现了,整理了一下。

结构示意图

(用 Process 在线画图工具画的)

eg01.jpg
说明
  • 外层容器的box高度不固定
  • 每列col的宽度可自定义
  • 列数可自定义,取决于有几个数据dataList,每个列的数据对应一个``dataList`
  • 页面布局结构代码
  <div class="box">
    <div class="col" ref="col1">
      <transition-group name="list">
        <div class="item" v-for="item in dataList1" :key="item.id">{{item.text}}</div>
      </transition-group>
    </div>
    <div class="col" ref="col2">
      <transition-group name="list">
        <div class="item" v-for="item in dataList2" :key="item.id">{{item.text}}</div>
      </transition-group>
    </div>
    <div class="col" ref="col3">
      <transition-group name="list">
        <div class="item" v-for="item in dataList3" :key="item.id">{{item.text}}</div>
      </transition-group>
    </div>
    <div class="col" ref="col4">
      <transition-group name="list">
        <div class="item" v-for="item in dataList4" :key="item.id">{{item.text}}</div>
      </transition-group>
    </div>
  </div>

加载数据

  • 使用axios
/** main.js*/
import Vue from 'vue'
import App from './App.vue'
import axios from 'axios'

Vue.prototype.$http = axios

new Vue({
  el: '#app',
  render: h => h(App)
})

  • 当组件mounted时获取数据,获取到数据后执行mountMenu()方法,mountMenu()方法将会通过selectCol()选择当前高度最小的列,并把数据push到对应的dataList中,``mountMenu()`会在每次执行时递归调用,直到遍历完所有的数据
/** 数据实例*/
[
  {
    id:1002,
    text:"mountMenu()中调用了this.$nextTick()目的是等待当前DOM渲染完成后在继续执行,否则在获取最小高度的列时,每次获取到的高度都为0(vm.nextTick()vue官方文档)"
  }
]
  • <span style='color:red;font-weight:bold'>重要信息</span>:mountMenu()中调用了this.$nextTick()目的是等待当前DOM渲染完成后在继续执行,否则在获取最小高度的列时,每次获取到的高度都为0(<a href="https://cn.vuejs.org/v2/api/#vm-nextTick" target="_blank">vm.nextTick()vue官方文档</a>)
export default {
  data() {
    return {
      mainMenuList: [],
      dataList1: [],
      dataList2: [],
      dataList3: [],
      dataList4: [],
    }
  },
  mounted() {
    this.$http({ url: 'http://localhost:6060/paragraph', method: 'get' }).then(res => {
      this.mainMenuList = res.data
      this.mountMenu()
    })
  },
  methods: {
    mountMenu(arg) {
      var temp = this.mainMenuList
      var index = arg || 0
      var refName = this.selectCol()
      if (temp.length > index) {
        this[refName].push(this.mainMenuList[index])
        this.$nextTick(() => {
          this.mountMenu(index + 1)
        })
      }
    },
    selectCol() {
      var getHeight = (ref) => {
        return this.$refs[ref].offsetHeight
      }
      var height1 = getHeight('col1')
      var height2 = getHeight('col2')
      var height3 = getHeight('col3')
      var height4 = getHeight('col4')
      switch (Math.min(height1, height2, height3, height4)) {
        case height1:
          return 'dataList1'
          break
        case height2:
          return 'dataList2'
          break
        case height3:
          return 'dataList3'
        case height4:
          return 'dataList4'
          break
      }
    },
  }
}
  • ie浏览器的BUG:上述代码在ie浏览器(ie 9/10/11)中会遇到动画的bug,目前我的解决方案就是js判断浏览器,在ie中禁用过渡动画(
    [doge]
    )
computed: {
    isIe() {
      var tmp = window.navigator.userAgent.indexOf("MSIE") >= 1
        || !!window.ActiveXObject
        || "ActiveXObject" in window
      return tmp ? "" : "list"
    }
}
<transition-group :name="isIe">
  <div class="item" v-for="item in dataList1" :key="item.id">{{item.text}}</div>
</transition-group>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前端开发面试题 面试题目: 根据你的等级和职位的变化,入门级到专家级,广度和深度都会有所增加。 题目类型: 理论知...
    怡宝丶阅读 2,611评论 0 7
  • 简介 在 vue 的官方文档中有一个 API 叫做 nextTick,将回调延迟到下次 DOM 更新循环之后执行。...
    西施老师阅读 1,498评论 0 0
  • vue 2.X 深入响应式原理的异步更新队列中说明如下: 只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一...
    指尖跳动阅读 9,526评论 1 11
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,148评论 1 32
  • 【转载】CSDN - 张林blog http://blog.csdn.net/XIAOZHUXMEN/articl...
    竿牍阅读 3,513评论 1 14