JavaScript瀑佈流的實現你學會瞭嗎
瀑佈流的核心
1, 根據 ajax請求的響應體結果 動態渲染生成頁面
請求地址 請求方式 參數鍵名 都是 後端程序定義的
前端 隻能根據需求 定義 攜帶的具體的參數數據
響應體數據是後端程序返回的數據結果
隻能獲取數據結果 不能修改數據結果
可以根據 響應體數據結果 動態渲染生成頁面內容
可以使用 三元運算符 給標簽定義屬性等
2, 瀑佈流 再次 發起請求的判斷依據
上卷高度 + 視窗窗口高度 + 預留高度 > 最矮ul占位高度
3, 函數的節流
同時觸發 多次執行 相同的函數程序
隻需要觸發執行 第一次 函數程序的調用
原理:
- 定義一個 開關變量
- 變量儲存原始數據
執行判斷
- 如果 變量 存儲原始數據 變量賦值其他數據
- 如果 變量 存儲其他數據 執行 return 終止之後程序的執行
當 函數的所有程序都觸發執行結束
變量 賦值原始值 可以再次觸發 新的函數
案例
這裡用某糖網站作為案例,調用某糖網站的接口,仿一個簡單的網頁。
代碼
<!DOCTYPE html> <html lang="en"> <head> <!-- 服務器加載網絡圖片的meta標簽 --> <meta name="referrer" content="never"> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } .btn { width: 300px; margin: 50px auto; } ul, ol, li { list-style: none; } img { display: block; width: 100%; height: 100%; } a, a:hover, a:active { text-decoration: none; } .box { width: 1200px; margin: 0 auto; } .box::after { display: block; content: ""; clear: both; } .box ul { width: 260px; float: left; margin: 0 20px; } .box ul li { width: 100%; display: flex; flex-direction: column; border: 2px solid #000; margin: 0 0 15px 0; } .box ul li .imgBox { width: 100%; } .box ul li .contentBox { width: 100%; padding: 15px; display: flex; flex-direction: column; justify-content: space-between; } .box ul li .contentBox p { display: flex; justify-content: flex-start; align-items: center; } .box ul li .contentBox p:nth-child(1) { margin: 10px 0; } .box ul li .contentBox p:nth-child(2) { margin: 10px 0; } .box ul li .contentBox p:nth-child(2) span { margin: 0 10px 0 0; } .box ul li .contentBox p:nth-child(2) span i { margin: 0 10px 0 0; } .box ul li .contentBox p:nth-child(3) span:nth-child(1) { display: block; width: 40px; height: 40px; border-radius: 50%; overflow: hidden; margin: 0 10px 0 0; } </style> </head> <body> <div class="btn"> <button>美食菜譜</button> <button>美妝造型</button> <button>傢居生活</button> <button>人物明星</button> </div> <!-- div中的內容是 動態生成的 --> <div class="box"></div> <script src="../../ajax.js"></script> <script> // 定義全局變量 存儲相關的數據信息 let start; let time; let keyword; // 獲取父級div標簽 const oBox = document.querySelector('.box'); // 定義全局變量 存儲 要使用的數據 let oUls; let flag = true; // 獲取 所有的button按鈕 const oBtns = document.querySelectorAll('button'); // 循環遍歷 給 所有的button標簽 添加 點擊事件 oBtns.forEach(item => { item.addEventListener('click', function () { // 默認第一次顯示的是從索引下標是0開始的第一條數據 start = 0; // 獲取關鍵詞 keyword = this.innerHTML; // 向 div標簽中寫入 4個ul空標簽 oBox.innerHTML = "<ul></ul><ul></ul><ul></ul><ul></ul>"; // 獲取 所有的ul標簽對象 oUls = oBox.querySelectorAll('ul'); // 調用執行 async await 和 promise執行的 ajax請求 setPage(); }) }) // 定義 頁面滾動監聽事件 window.addEventListener('scroll', function () { // 獲取 占位數據數值 // 頁面上卷高度 let scrollTop = document.documentElement.scrollTop; // 視窗窗口占位高度 let winHeight = document.documentElement.clientHeight; // 設定預留高度 let height = 500; // 獲取最矮ul標簽對象 // 循環結束 minUl 變量中 存儲 最矮ul標簽對象 let minUl = oUls[0]; for (let i = 0 + 1; i <= oUls.length - 1; i++) { // 如果 minUl 變量中 存儲的 ul標簽 高度 大於 oUls[i]循環遍歷的ul標簽的占位 // 變量minUl 中 存儲 oUls[i] 循環遍歷的ul標簽 if (minUl.offsetHeight > oUls[i].offsetHeight) { minUl = oUls[i]; } } // 執行判斷 if (scrollTop + winHeight + height > minUl.offsetHeight) { // 再次發起請求 動態渲染生成新的頁面內容 /* 因為 scroll事件 鼠標滾動一次 多次觸發 scroll事件 也就是 鼠標滾動一次 多次觸發執行 setPage() 函數 也就是 鼠標滾動一次 多次觸發執行 新的 ajax請求 因為 ajax請求是異步程序 結果就是 多次觸發的ajax請求 執行的是相同的請求參數 獲取的 響應體結果 是 相同的響應體結果 實際項目中 多次請求 隻需要執行 第一次請求 */ // 判斷變量儲存的數據 防止多次調用函數 if (flag) { flag = false; } else { return; } // 再次調用函數 發起新的請求 動態渲染生成新的頁面 setPage(); } }) // 使用 async 定義 異步請求函數程序 async function setPage() { // 獲取 時間對象 和 時間戳 const t = new Date(); time = t.getTime(); // 發起請求時 根據需求 設定 ajax請求攜帶的參數數據 // response中存儲的是響應體數據 const response = JSON.parse(await myPromiseAjax('/dt', 'get', `include_fields=top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count&filter_id=${keyword}&start=${start}&_=${time}`)); console.log(response); // 給下一次 請求 賦值起始數據的索引下標 start = response.data.next_start; // 獲取 24條數據的數組 const arr = response.data.object_list; // 循環遍歷 數組中的24個單元 arr.forEach(item => { // 根據數組單元的數據 生成 li標簽 let str = ` <li> <div class="imgBox" style="height:${260 * item.photo.height / item.photo.width}px"> <img src="${item.photo.path}" alt=""> </div> <div class="contentBox"> <p>${item.msg}</p> <p> <span style="${item.like_count === 0 ? 'display:none' : ''}"> <i>點贊</i>${item.like_count} </span> <span style="${item.favorite_count === 0 ? 'display:none' : ''}"> <i>收藏</i>${item.favorite_count} </span> </p> <p> <span> <img src="${item.sender.avatar}" alt=""> </span> <span> ${item.sender.username} <br> 發佈到 <a href="JavaScript:;">${item.album.name}</a> </span> </p> </div> </li>`; // 每生成一個li 就要拼接寫入最矮的ul標簽中 // 獲取最矮的ul標簽 let minUl = oUls[0]; for (let i = 0 + 1; i <= oUls.length - 1; i++) { // 如果 minUl 變量中 存儲的 ul標簽 高度 大於 oUls[i]循環遍歷的ul標簽的占位 // 變量minUl 中 存儲 oUls[i] 循環遍歷的ul標簽 if (minUl.offsetHeight > oUls[i].offsetHeight) { minUl = oUls[i]; } } // 循環結束minUl 中 存儲的是 最矮的ul標簽對象 // 向 最矮的ul標簽中 拼接寫入 li標簽 minUl.innerHTML += str; }) // 當請求執行結束 當新的頁面內容生成完畢 // 可以再次發起新的請求 給 變量賦值原始數據 flag = true; } </script> </body> </html>
ajax代碼
// 封裝一個promise程序執行 ajax請求 // 參數1 請求的url地址 // 參數2 請求的方式 // 參數3 攜帶的參數怇 function myPromiseAjax( url , type = 'get' , data = '' ){ // 創建一個 promise 對象 const p = new Promise(function( fulfilled , rejected ){ // 執行異步ajax請求 const xhr = new XMLHttpRequest() ; if( type.toLowerCase() === 'get' ){ // get請求方式 xhr.open( 'get' , `${url}?${data}` ); xhr.send(); }else{ // post請求方式 xhr.open( 'post' , url ); xhr.setRequestHeader('Content-Type' , 'application/x-www-form-urlencoded'); xhr.send(data); } // 接收 請求結果 xhr.onreadystatechange = function(){ // 當 ajax狀態碼是 4 時 判斷 http狀態碼 if( xhr.readyState === 4 ) { // 如果 http狀態碼 是 200 - 299 if( /^2\d{2}$/.test( xhr.status ) ){ // 請求成功 fulfilled( xhr.response ); }else if( /^(4|5)\d{2}$/.test( xhr.status ) ){ // 請求失敗 rejected( xhr.statusText ); } } } }); // return 返回這個promise對象 return p; }
註意點
(1)服務器加載網絡圖片的meta標簽
(2)瀑佈流執行的判斷依據
(3)函數的節流
(4)服務器配置更改
運行結果
總結
本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!