vue實現網路圖片瀑布流 + 下拉刷新 + 上拉載入更多

来源:https://www.cnblogs.com/tandaxia/archive/2020/01/14/12189301.html
-Advertisement-
Play Games

一、思路分析和效果圖 用vue來實現一個瀑布流效果,載入網路圖片,同時有下拉刷新和上拉載入更多功能效果。然後針對這幾個效果的實現,捋下思路: 先看個效果動圖: 靜態截圖: 二、具體實現步驟 2.1、頁面結構設計,測試數據準備。 本地準備一個json文件數據,放在項目public文件夾下。註意,本地測 ...


一、思路分析和效果圖

  用vue來實現一個瀑布流效果,載入網路圖片,同時有下拉刷新和上拉載入更多功能效果。然後針對這幾個效果的實現,捋下思路:

  1. 根據載入數據的順序,依次追加標簽展示效果;
  2. 選擇哪種方式實現瀑布流,這裡選擇絕對定位方式;
  3. 關鍵問題:由於每張圖片的寬高不一樣,而瀑布流中要求所有圖片的寬度一致,高度隨寬度等比縮放。而且由於圖片的載入是非同步延遲。在不知道圖片高度的情況下,每個圖片所在的item盒子不好絕對定位。因此在渲染頁面前先獲取所有圖片的高度,是解決問題的關鍵點!這裡選擇用JS中的Image類,通過預載入圖片的方式提前獲取圖片寬高,另外通過一個臨時變數來計算是否所有圖片的高度已經得到。當所有的圖片高度獲取後,開始渲染頁面。
  4. 頁面渲染後,獲取所有圖片所在的盒子,迴圈計算盒子的高度,開始設置每個盒子item的絕對定位。
  5. 頁面渲染時,會出現閃爍的現象。如何解決這個問題呢?這裡用了一個動畫樣式。不過在第一次載入的時候,還是會有一點閃爍的感覺。
  6. 然後就是下拉刷新和上拉載入更多的效果,這裡用了有贊的vant組件PullRefresh和List這套組合組件來實現。

先看個效果動圖:

靜態截圖:

 

二、具體實現步驟

2.1、頁面結構設計,測試數據準備。

   本地準備一個json文件數據,放在項目public文件夾下。註意,本地測試數據必須放在public文件夾下,網路請求時才能請求到數據,這是vue3.x。新增加一個axios依賴包,用來進行網路請求。部分截圖,及關鍵代碼:

//數據請求
getDataList(){
    this.$axios.get("/json/dataList.json").then((res)=>{

         let list = res.data.data ? res.data.data: [];
         if (list.length > 0){
             //從list中取pageSize條數據出來
             var tempList = [];
              for (let i = 0; i < this.pageSize; i++){
                   if (list.length > 0){
                      let tempIndex = parseInt(Math.random() * 1000) % list.length;
                      tempList.push(list[tempIndex]);
                      list.splice(tempIndex, 1);
                  }
              }
               this.loadImagesHeight(tempList); //模擬預載入圖片,獲取圖片高度
          }
          else {
              this.loadImagesHeight(list); 
          }
      }).catch((res)=>{
           console.log("..fail: ", res);
           this.$toast.clear();
           this.isLoading = false; //下拉刷新請求完成
           this.loading = false; //上拉載入更多請求完成
     })
},

 

2.2、預載入圖片,存儲圖片高度

  獲取數據後,遍曆數據數組,預載入圖片,計算圖片縮放後的高度,存儲起來。同時由於圖片載入是非同步載入,所以用變數計數,當最後一個圖片載入完成後,開始渲染頁面。

loadImagesHeight(list){
                var count = 0; //用來計數,表示是否所有圖片高度已經獲取
                list.forEach((item, index)=>{
                    //創建圖片對象,載入圖片,計算圖片高度
                    var img = new Image();
                    img.src = item.cover;
                    img.onload = img.onerror = (e)=>{
                        count++;
                        if (e.type == 'load'){ //圖片載入成功
                            //計算圖片縮放後的高度:圖片原高度/原寬度 = 縮放後高度/縮放後寬度
                            list[index].imgHeight = Math.round(img.height * this.boxWidth / img.width);
                            // console.log('index: ', index, ', load suc, imgHeiht: ', list[index].imgHeight);
                        }
                        else{ //圖片載入失敗,給一個預設高度50
                            list[index].imgHeight = 50;
                            console.log("index: ", index, ", 載入報錯:", e);
                        }

                        //載入完成最後一個圖片高度,開始下一步數據處理
                        if (count == list.length){
                            this.resolveDataList(list);
                        }
                    }
                })
},
View Code

 

2.3、渲染頁面,設置絕對定位

  所有圖片通過預載入獲取圖片高度後,開始渲染頁面。然後遍歷所有圖片所在盒子標簽,獲取盒子高度,設置每個盒子的絕對定位。

resolveDataList(list){ //處理數據
                //下拉刷新,清空原數據
                if (this.pageIndex <= 1){
                    this.itemCount = 0;
                    this.dataList = [];
                    this.lastRowHeights = [0, 0]; //存儲每列的最後一行高度清0
                }

                if (list.length >= this.pageSize){
                    this.pageIndex++;  //還有下一頁
                }
                else{
                    this.finished = true; //當前tab類型下所有數據已經載入完成
                }

                //合併新老兩個數組數據
                this.dataList = [...this.dataList, ...list];
                //判斷頁面是否有數據
                this.haveData = this.dataList.length > 0 ? 2 : 1;
                this.isLoading = false; //下拉刷新請求完成
                this.loading = false; //上拉載入更多請求完成

                console.log("...datalist: ", this.dataList);
                console.log("...this.isLoading: ", this.isLoading)

                this.$nextTick(()=>{
                    setTimeout(()=>{
                        //渲染完成,計算每個item寬高,設置標簽坐標定位
                        this.setItemElementPosition();
                        this.isLoading = false; //下拉刷新請求完成
                        this.loading = false; //上拉載入更多請求完成
                    }, 1000)
                });
            },
            //獲取每個item標簽高度,設置item的定位
            setItemElementPosition(){
                let parentEle = document.getElementById('data-list-box');
                let boxEles = parentEle.getElementsByClassName("data-item");

                for (let i = this.itemCount; i < boxEles.length; i++){
                    let tempEle = boxEles[i];
                    //上一個標簽最小高度的列索引
                    let curColIndex = this.getMinHeightIndex(this.lastRowHeights);
                    let boxTop = this.lastRowHeights[curColIndex] + this.boxMargin;
                    let boxLeft = curColIndex * (this.boxWidth + this.boxMargin) + this.boxMargin;
                    tempEle.style.left = boxLeft + 'px';
                    tempEle.style.top = boxTop + 'px';
                    this.lastRowHeights[curColIndex] = boxTop + tempEle.offsetHeight;

                    // console.log('i = ', i, ', boxTop: ', boxTop, ', eleHeight: ', tempEle.offsetHeight);
                }

                this.itemCount = boxEles.length;

                //修改父級標簽的高度
                let maxHeight = Math.max.apply(null, this.lastRowHeights);
                parentEle.style.height = maxHeight + 'px';

                this.$toast.clear();
                console.log("...boxEles: ", boxEles.length, ", maxH: ", maxHeight);
            },
View Code

 

2.4、其他說明

  其他頁面中如下拉刷新,和上拉載入更多等功能,使用了有贊的組件庫中的PullRefreshList這一套組合組件。感覺效果挺棒的,使用步驟也簡單。另外就是在頁面渲染時,會出現頁面閃爍的現象,後面使用了一個css動畫處理了這個現象,效果好了很多。但是在第一次載入的時候,還是有輕微的閃爍現象。等後面找到更好的方法,再更新。

 

完整效果DEMO地址:https://github.com/xiaotanit/tan_vue/blob/master/src/views/PageWaterFall.vue


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前提要述:參考書籍《MySQL必知必會》 《MySQL必知必會》是先講了查詢,但是沒有記錄就無法查詢,所以先將如何添加數據。 表已經知道怎麼創建了,隨便創兩張。 5.1 插入數據 MySQL使用 INSERT來插入(或添加)行(記錄)到資料庫表中。插入可用以下幾種方式使用: 插入完整的行(記錄); ...
  • #!/bin/bash echo "修改主機名" hostnamectl set-hostname wangxfa hostname sleep 1 echo "查看並關閉防火牆" systemctl status firewalld systemctl stop firewalld systemc ...
  • 屬性順序錯誤 一般情況下欄位類型要放在前面,限制參數放在後面,UNSIGNEDZEROFILL 之間沒有先後順序,主鍵 KEY 和 auto_increment 要放在UNSIGNED ZEROFILL 後面 否則報錯 。設置為主鍵的欄位沒有 deafault參數,not null 一般放在最後面。 ...
  • # 註釋內容 -- 註釋內容 -- 創建資料庫 king CREATE DATABASE king; -- 查看當前伺服器下有哪些資料庫 SHOW DATABASES; SHOW SCHEMAS; -- 查看king資料庫的詳細信息 SHOW CREATE DATABASE king; -- 創建數 ...
  • 提到Redis,大家肯定都聽過,並且應該都在項目中或多或少的使用過,也許你覺得Redis用起來挺簡單的呀,但如果有人問你下麵的幾個問題(比如同事或者面試官),你能回答的上來嗎? 1. 什麼是Redis? 2. Redis能存儲哪幾種數據結構? 3. Redis有幾種持久化機制?它們的優缺點分別是什麼 ...
  • 前提要述:參考書籍《MySQL必知必會》 2.1 MySQL簡介 2.1.1 什麼是MySQL MySQL是一種關係資料庫管理系統。負責資料庫中數據的存儲,檢索,管理和處理。 2.1.2 MySQL的優點 成本低——MySQL是開源的,一般可以免費使用。 性能——MySQL執行快。 可信賴,體積小。 ...
  • 個人博客 "http://www.milovetingting.cn" AOP之AspectJ的簡單使用 AOP的定義 AOP為Aspect Oriented Programming的縮寫,意為:面向切麵編程,通過預編譯方式和運行期間動態代理實現程式功能的統一維護的一種技術。 以上關於AOP的定義引 ...
  • 這是一個很長很長的story!-芝麻粒兒創作 開篇 源碼地址:GitHub 本文目的,將Unity集成到Android端,學完本文後你可以做到 Android任意佈局載入Unity 3D場景 任意操作佈局中的按鈕/3D物品(縮放旋轉等) 互相消息通信(你叼我,我叼你) 自由切換Unity中的場景 動 ...
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...