美文网首页让前端飞前端开发Web前端之路
vue使用列表渲染 实现瀑布流布局

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

作者: Mario34 | 来源:发表于2019-05-14 16:53 被阅读23次

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

    结构示意图

    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官方文档)"
      }
    ]
    
    • 重要信息mountMenu()中调用了this.$nextTick()目的是等待当前DOM渲染完成后在继续执行,否则在获取最小高度的列时,每次获取到的高度都为0(vue官方文档:https://cn.vuejs.org/v2/api/#vm-nextTickvm.nextTick()
    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>
    

    相关文章

      网友评论

        本文标题:vue使用列表渲染 实现瀑布流布局

        本文链接:https://www.haomeiwen.com/subject/qrkeaqtx.html