vue中瀑布流布局

2022-08-16  本文已影响0人  keknei

假如说我们列表需要四列,html就用四个ul,并且平均分配宽度为25%,然后每次渲染一条数据进去,就算一遍这个四个ul的高度,那个ul高最小,就把数据插入到那个ul里面

<div class="source-list clearfix" id="sourceBox">
  <ul data-id="0">
    <li v-for="(item,index) in columnSourceList[0]" :key="index"></li>
  </ul>
  <ul data-id="1">
     <li v-for="(item,index) in columnSourceList[1]" :key="index"></li>
  </ul>
  <ul data-id="2">
     <li v-for="(item,index) in columnSourceList[2]" :key="index"></li>
  </ul>
  <ul data-id="3">
    <li v-for="(item,index) in columnSourceList[3]" :key="index"></li>
  </ul>
</div>

less设置,因为flex布局,会默认子级等高布局,并且我们得算每个ul的高度所以必须得设置align-items:flex-start;

.source-list{
    display:flex;
    align-items:flex-start;
    justify-content:space-between;
    ul{
      width:25%;
      max-width:300px;
    }
    li{
      border:1px solid #f0f0f0;
      border-radius:6px;
      position:relative;
      margin-bottom:20px;
    }
  }

js中,等我们请求完接口拿到数据之后,就去拿到四个ul元素,并且开始算高度,排序之后给高度最低的ul插入数据

  data () {
    return {
      columnSourceList:[[],[],[],[]],//存放素材每一列的数据,共四列
    }
  },
  mounted(){//mounted中可以获取到元素,created中获取不到
    //添加滚动事件
    window.onscroll=function (){
      let height=document.body.scrollHeight;
      let clientHeight=document.documentElement.clientHeight;
      let scrollTop=document.documentElement.scrollTop || document.body.scrollTop;
        
      if (clientHeight+scrollTop+50 > height){
        this.getListData();
      }
    };
    this.getListData();
  },
  methods:{
    async getListData(){//获取素材列表
      let {data}=await getListApi();//请求接口
      this.sourceList=data.list;
      //请求玩接口拿到数据后获取四个ul放到数组中
      const aUl=document.querySelectorAll("#sourceBox>ul");
      for(let i=0;i<aUl.length;i++){
        this.elArr.push(aUl[i]);
      }
      this.pushData();
    },
    pushData(){//给高度最低的ul放入数据
      let item=this.sourceList.shift();
      if(item){//如果有数据才高度排序插入数据
        this.elArr.sort((a,b)=>{//给ul的高度排序,由小到大
          return a.offsetHeight-b.offsetHeight
        });
        //获取这个高度最小的ul上面的index,知道是往那个ul上插入数据
        let index=Number.parseInt(this.elArr[0].dataset.id);
        //push完数据,继续调用
        this.columnSourceList[index].push(item);
        this.$nextTick(()=>{
          this.pushData();
        });
      }
    }
  }

之所以用this.sourceList.shift()方法和递归来获取第一条数据并插入,而不用forEach循环来获取数据插入ul,是因为forEach无法满足获取ul的高度,在forEach中获取的高度都是一样的,因为vue中插入数据然后渲染也是需要时间的,所以在forEach获取ul的高度会一直是0

      this.sourceList.forEach(item=>{
        this.elArr.sort((a,b)=>{
          return a.offsetHeight-b.offsetHeight
        });
        let index=Number.parseInt(this.elArr[0].dataset.id);
        console.log(this.elArr[0].offsetHeight)//0
        this.columnSourceList[index].push(item);
      })
上一篇 下一篇

猜你喜欢

热点阅读