vuejs实现瀑布流布局(一)

一直以来,习惯了jquery的DOM操做方式,忽然间,开始学习使用vuejs,不少时候,操做DOM观念老是转换不过来,虽然也能实现各类效果,可是总有点不三不四的。javascript

就相似于最近在作的瀑布流布局,正常的方式完成,而且上线以后,做为练手,也使用vuejs来走了一趟。html

需求:瀑布流布局照片墙vue

使用了SUI-Mobile结合vuejs。java

实现过程: jquery

<div class="waterfalls"> 
   <ul id="waterfalls-left">
   </ul>
   <ul id="waterfalls-right">
   </ul>
   <ul id="items">
   </ul>
</div>

 前两个ul做为实际布局须要存在的,就是瀑布流的左边和右边两部分,而第三个id为items的ul,其实是做为中转出现的。 app

   <ul id="items">
      <li v-for="photo in photos">
        <router-link :to="'detail/'+photo.id">
          <img :src="photo.src" alt="">
          <span v-show="photo.isDel" @click.stop.prevent="noLink">{{photo.delDesc}}</span>
        </router-link>
        <div class="desc-info">
          <p>编号:<span>{{photo.numbering}}</span></p>
        </div>
        <div class="card-footer no-border">
          <a href="#" :class="['link custom-link']" @click.prevent.stop="praise">{{photo.praise || 0}}</a>
          <span></span>
          <a href="#" class="link custom-link">编辑</a>
          <span></span>
          <a href="#" class="link custom-link">删除</a>
        </div>
      </li>
    </ul>

  在ul#items里面循环产生全部须要加载的li,缘由在于:彻底依据数据,是没办法哪条数据最终生成的li的高度是多少,从而没法判断这条数据是应该添加在左边仍是右边的。工具

  下面就是将ul#items里面生成的li逐个的搬到ul#waterfalls-left或者ul#waterfalls-right里面。  布局

$("#items").children("li").each(function (index, val) {
    // 相关搬迁的代码
});

若是直接这么写的话,会发现没有数据,可是当你打印数据的时候,又确实是存在相关数据,经过开发者工具也彻底可以查到相关DOM结构的,关键问题在于选取$("#items")时,vuejs尚未彻底生成相关结构,因此最简单的解决方案是加延时setTimeout();学习

setTimeout(function () {
          $("#items").children("li").each(function (index, val) {
                 // 相关搬迁的代码
          })
}, 0);    

  并不须要具体的延时时间。测试

  相关搬迁代码,有一个关键点是,若是ul#waterfalls-left的height小于等于ul#waterfalls-right的height的话,就往ul#waterfalls-left追加,不然追加到ul#waterfalls-right。计算其实际高度的时候,li高度必须彻底被撑起来,而li的实际高度是有img的高度决定的。那么很天然的会想到,高度计算必须是在img.onload以后计算的。

            var $this = $(this);
            var $img = $this.find("img").first();

            $img.on("load", function () {
                addItems();
            });

            function addItems() {
              if(_this.leftHeight <= _this.rightHeight){
                $l.append($this);
                _this.leftHeight = $l.height();
              }else{
                $r.append($this);
                _this.rightHeight = $r.height();
              }
            }

  到这里,基本上已经实现了所须要的瀑布流效果,可是通过测试以后,发现存在另外一个问题,就是当第一次加载完成以后,直接刷新页面的话,数据会彻底丢失。是由于数据已经存在,因此走不到img.onload里面去了(不知道为何),解决方案是判断img.complete。同时,保险起见,添加若是图片加载失败的替代图片。

修改以后的代码为:

       var _this = this,
            $l = $("#waterfalls-left"),
            $r = $("#waterfalls-right");

        setTimeout(function () {
          $("#items").children("li").each(function (index, val) {
            var $this = $(this);
            var $img = $this.find("img").first();
            $img.on("error", function () {
              $img.attr("src", "../src/assets/images/default.png");
            });

            if ($img.get(0).complete) {
              addItems();
            } else {
              $img.on("load", function () {
                addItems();
              });
            }

            function addItems() {
              if(_this.leftHeight <= _this.rightHeight){
                $l.append($this);
                _this.leftHeight = $l.height();
              }else{
                $r.append($this);
                _this.rightHeight = $r.height();
              }
            }
          });
        }, 0);
相关文章
相关标签/搜索