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);
相關文章
相關標籤/搜索