JavaScript瀑布流的實(shí)現(xiàn)你學(xué)會(huì)了嗎
瀑布流的核心
1, 根據(jù) ajax請(qǐng)求的響應(yīng)體結(jié)果 動(dòng)態(tài)渲染生成頁面
請(qǐng)求地址 請(qǐng)求方式 參數(shù)鍵名 都是 后端程序定義的
前端 只能根據(jù)需求 定義 攜帶的具體的參數(shù)數(shù)據(jù)
響應(yīng)體數(shù)據(jù)是后端程序返回的數(shù)據(jù)結(jié)果
只能獲取數(shù)據(jù)結(jié)果 不能修改數(shù)據(jù)結(jié)果
可以根據(jù) 響應(yīng)體數(shù)據(jù)結(jié)果 動(dòng)態(tài)渲染生成頁面內(nèi)容
可以使用 三元運(yùn)算符 給標(biāo)簽定義屬性等
2, 瀑布流 再次 發(fā)起請(qǐng)求的判斷依據(jù)
上卷高度 + 視窗窗口高度 + 預(yù)留高度 > 最矮ul占位高度
3, 函數(shù)的節(jié)流
同時(shí)觸發(fā) 多次執(zhí)行 相同的函數(shù)程序
只需要觸發(fā)執(zhí)行 第一次 函數(shù)程序的調(diào)用
原理:
- 定義一個(gè) 開關(guān)變量
- 變量儲(chǔ)存原始數(shù)據(jù)
執(zhí)行判斷
- 如果 變量 存儲(chǔ)原始數(shù)據(jù) 變量賦值其他數(shù)據(jù)
- 如果 變量 存儲(chǔ)其他數(shù)據(jù) 執(zhí)行 return 終止之后程序的執(zhí)行
當(dāng) 函數(shù)的所有程序都觸發(fā)執(zhí)行結(jié)束
變量 賦值原始值 可以再次觸發(fā) 新的函數(shù)
案例
這里用某糖網(wǎng)站作為案例,調(diào)用某糖網(wǎng)站的接口,仿一個(gè)簡單的網(wǎng)頁。
代碼
<!DOCTYPE html> <html lang="en"> <head> <!-- 服務(wù)器加載網(wǎng)絡(luò)圖片的meta標(biāo)簽 --> <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中的內(nèi)容是 動(dòng)態(tài)生成的 --> <div class="box"></div> <script src="../../ajax.js"></script> <script> // 定義全局變量 存儲(chǔ)相關(guān)的數(shù)據(jù)信息 let start; let time; let keyword; // 獲取父級(jí)div標(biāo)簽 const oBox = document.querySelector('.box'); // 定義全局變量 存儲(chǔ) 要使用的數(shù)據(jù) let oUls; let flag = true; // 獲取 所有的button按鈕 const oBtns = document.querySelectorAll('button'); // 循環(huán)遍歷 給 所有的button標(biāo)簽 添加 點(diǎn)擊事件 oBtns.forEach(item => { item.addEventListener('click', function () { // 默認(rèn)第一次顯示的是從索引下標(biāo)是0開始的第一條數(shù)據(jù) start = 0; // 獲取關(guān)鍵詞 keyword = this.innerHTML; // 向 div標(biāo)簽中寫入 4個(gè)ul空標(biāo)簽 oBox.innerHTML = "<ul></ul><ul></ul><ul></ul><ul></ul>"; // 獲取 所有的ul標(biāo)簽對(duì)象 oUls = oBox.querySelectorAll('ul'); // 調(diào)用執(zhí)行 async await 和 promise執(zhí)行的 ajax請(qǐng)求 setPage(); }) }) // 定義 頁面滾動(dòng)監(jiān)聽事件 window.addEventListener('scroll', function () { // 獲取 占位數(shù)據(jù)數(shù)值 // 頁面上卷高度 let scrollTop = document.documentElement.scrollTop; // 視窗窗口占位高度 let winHeight = document.documentElement.clientHeight; // 設(shè)定預(yù)留高度 let height = 500; // 獲取最矮ul標(biāo)簽對(duì)象 // 循環(huán)結(jié)束 minUl 變量中 存儲(chǔ) 最矮ul標(biāo)簽對(duì)象 let minUl = oUls[0]; for (let i = 0 + 1; i <= oUls.length - 1; i++) { // 如果 minUl 變量中 存儲(chǔ)的 ul標(biāo)簽 高度 大于 oUls[i]循環(huán)遍歷的ul標(biāo)簽的占位 // 變量minUl 中 存儲(chǔ) oUls[i] 循環(huán)遍歷的ul標(biāo)簽 if (minUl.offsetHeight > oUls[i].offsetHeight) { minUl = oUls[i]; } } // 執(zhí)行判斷 if (scrollTop + winHeight + height > minUl.offsetHeight) { // 再次發(fā)起請(qǐng)求 動(dòng)態(tài)渲染生成新的頁面內(nèi)容 /* 因?yàn)?scroll事件 鼠標(biāo)滾動(dòng)一次 多次觸發(fā) scroll事件 也就是 鼠標(biāo)滾動(dòng)一次 多次觸發(fā)執(zhí)行 setPage() 函數(shù) 也就是 鼠標(biāo)滾動(dòng)一次 多次觸發(fā)執(zhí)行 新的 ajax請(qǐng)求 因?yàn)?ajax請(qǐng)求是異步程序 結(jié)果就是 多次觸發(fā)的ajax請(qǐng)求 執(zhí)行的是相同的請(qǐng)求參數(shù) 獲取的 響應(yīng)體結(jié)果 是 相同的響應(yīng)體結(jié)果 實(shí)際項(xiàng)目中 多次請(qǐng)求 只需要執(zhí)行 第一次請(qǐng)求 */ // 判斷變量儲(chǔ)存的數(shù)據(jù) 防止多次調(diào)用函數(shù) if (flag) { flag = false; } else { return; } // 再次調(diào)用函數(shù) 發(fā)起新的請(qǐng)求 動(dòng)態(tài)渲染生成新的頁面 setPage(); } }) // 使用 async 定義 異步請(qǐng)求函數(shù)程序 async function setPage() { // 獲取 時(shí)間對(duì)象 和 時(shí)間戳 const t = new Date(); time = t.getTime(); // 發(fā)起請(qǐng)求時(shí) 根據(jù)需求 設(shè)定 ajax請(qǐng)求攜帶的參數(shù)數(shù)據(jù) // response中存儲(chǔ)的是響應(yīng)體數(shù)據(jù) 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); // 給下一次 請(qǐng)求 賦值起始數(shù)據(jù)的索引下標(biāo) start = response.data.next_start; // 獲取 24條數(shù)據(jù)的數(shù)組 const arr = response.data.object_list; // 循環(huán)遍歷 數(shù)組中的24個(gè)單元 arr.forEach(item => { // 根據(jù)數(shù)組單元的數(shù)據(jù) 生成 li標(biāo)簽 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>點(diǎn)贊</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> 發(fā)布到 <a href="JavaScript:;">${item.album.name}</a> </span> </p> </div> </li>`; // 每生成一個(gè)li 就要拼接寫入最矮的ul標(biāo)簽中 // 獲取最矮的ul標(biāo)簽 let minUl = oUls[0]; for (let i = 0 + 1; i <= oUls.length - 1; i++) { // 如果 minUl 變量中 存儲(chǔ)的 ul標(biāo)簽 高度 大于 oUls[i]循環(huán)遍歷的ul標(biāo)簽的占位 // 變量minUl 中 存儲(chǔ) oUls[i] 循環(huán)遍歷的ul標(biāo)簽 if (minUl.offsetHeight > oUls[i].offsetHeight) { minUl = oUls[i]; } } // 循環(huán)結(jié)束minUl 中 存儲(chǔ)的是 最矮的ul標(biāo)簽對(duì)象 // 向 最矮的ul標(biāo)簽中 拼接寫入 li標(biāo)簽 minUl.innerHTML += str; }) // 當(dāng)請(qǐng)求執(zhí)行結(jié)束 當(dāng)新的頁面內(nèi)容生成完畢 // 可以再次發(fā)起新的請(qǐng)求 給 變量賦值原始數(shù)據(jù) flag = true; } </script> </body> </html>
ajax代碼
// 封裝一個(gè)promise程序執(zhí)行 ajax請(qǐng)求 // 參數(shù)1 請(qǐng)求的url地址 // 參數(shù)2 請(qǐng)求的方式 // 參數(shù)3 攜帶的參數(shù)怇 function myPromiseAjax( url , type = 'get' , data = '' ){ // 創(chuàng)建一個(gè) promise 對(duì)象 const p = new Promise(function( fulfilled , rejected ){ // 執(zhí)行異步ajax請(qǐng)求 const xhr = new XMLHttpRequest() ; if( type.toLowerCase() === 'get' ){ // get請(qǐng)求方式 xhr.open( 'get' , `${url}?${data}` ); xhr.send(); }else{ // post請(qǐng)求方式 xhr.open( 'post' , url ); xhr.setRequestHeader('Content-Type' , 'application/x-www-form-urlencoded'); xhr.send(data); } // 接收 請(qǐng)求結(jié)果 xhr.onreadystatechange = function(){ // 當(dāng) ajax狀態(tài)碼是 4 時(shí) 判斷 http狀態(tài)碼 if( xhr.readyState === 4 ) { // 如果 http狀態(tài)碼 是 200 - 299 if( /^2\d{2}$/.test( xhr.status ) ){ // 請(qǐng)求成功 fulfilled( xhr.response ); }else if( /^(4|5)\d{2}$/.test( xhr.status ) ){ // 請(qǐng)求失敗 rejected( xhr.statusText ); } } } }); // return 返回這個(gè)promise對(duì)象 return p; }
注意點(diǎn)
(1)服務(wù)器加載網(wǎng)絡(luò)圖片的meta標(biāo)簽
(2)瀑布流執(zhí)行的判斷依據(jù)
(3)函數(shù)的節(jié)流
(4)服務(wù)器配置更改
運(yùn)行結(jié)果
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Javascript中內(nèi)建函數(shù)reduce的應(yīng)用詳解
內(nèi)建函數(shù)其實(shí)就是內(nèi)置函數(shù),reduce函數(shù)是ECMAScript5規(guī)范中出現(xiàn)的數(shù)組方法。在平時(shí)的工作中,相信大家使用的場(chǎng)景并不多,這篇文章給大家詳細(xì)介紹了函數(shù)reduce的應(yīng)用以及多重疊加,有需要的朋友們可以參考借鑒,下面來一起看看吧。2016-10-10javascript強(qiáng)制彈出新窗口實(shí)現(xiàn)代碼
javascript強(qiáng)制彈出新窗口,主要是利用的動(dòng)態(tài)創(chuàng)建鏈接。2009-12-12跟我學(xué)習(xí)javascript的undefined與null
跟我學(xué)習(xí)javascript的undefined與null,從定義上理解null和undefined,告訴大家提高undefined性能的方法,感興趣的小伙伴們可以參考一下2015-11-11JS運(yùn)算符優(yōu)先級(jí)與表達(dá)式示例詳解
這篇文章主要給大家介紹了關(guān)于JS運(yùn)算符優(yōu)先級(jí)與表達(dá)式的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09JavaScript 開發(fā)工具webstrom使用指南
本文給大家推薦了一款非常熱門的javascript開發(fā)工具webstrom,著重介紹了webstrom的特色功能、設(shè)置技巧、使用心得以及快捷鍵匯總,非常的全面。2014-12-12js 點(diǎn)擊按鈕彈出另一頁,選擇值后,返回到當(dāng)前頁
js 點(diǎn)擊按鈕彈出另一頁,選擇值后,返回到當(dāng)前頁,其實(shí)主要用于cms系統(tǒng)中,相關(guān)文章的搜索,要在已上傳目錄中選擇一些圖片等。2010-05-05javascript-hashchange事件和歷史狀態(tài)管理實(shí)例分析
這篇文章主要介紹了javascript-hashchange事件和歷史狀態(tài)管理,結(jié)合實(shí)例形式分析了javascript-hashchange基本功能、原理及歷史狀態(tài)管理相關(guān)操作技巧,需要的朋友可以參考下2020-04-04改版了網(wǎng)上的一個(gè)js操作userdata
改版了網(wǎng)上的一個(gè)js操作userdata,并根據(jù)其它網(wǎng)友的文章結(jié)合了下。希望對(duì)需要的朋友有所幫助。2007-04-04