完整程式碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>瀑布流</title> <style type="text/css"> img { width: 300px; } li { position: absolute; s left: 0; top: 0; list-style: none; } ul { margin: 0 auto; position: relative; } * { margin: 0; padding: 0; } </style> </head> <body> <ul></ul> </body> <script src="utils.js"></script> <script> let ul = document.querySelector('ul'), //獲取ul標籤 list = ul.children, //動態更新ul裡面的子元素 teep = 10, //間距 width = 300, //每張圖片的寬度 cols = Math.floor(document.documentElement.clientWidth / (width + teep)), //計算有多少列 hh = [], //存取每一列的高度 num = 0, //記錄載入完成圖片數量 om = 0 //記錄已經排版完成的li數量 ul.style.width = cols * (width + teep) - teep + 'px' //計算ul的寬度 get({ //提前封裝好的方法 url: 'http://rap2.taobao.org:38080/app/mock/256901/json' }) .then(a => { //請求資料成功 a = JSON.parse(a).img let dom = document.createDocumentFragment() //建立文件碎片 a.forEach((item, index) => { //有多少條資料就建立多少個li let li = document.createElement('li') li.innerHTML = `<img src="${item.src}">` dom.appendChild(li) //把li新增到文件碎片中 }) ul.appendChild(dom) //將文件碎片新增到ul中 let imgs = Array.from(list).reduce((curr, item, index) => { //將每張img節點組成陣列 if (om <= index) { curr.push(item.querySelector('img')) } return curr }, []) Array.from(imgs).forEach(item => { //遍歷每張圖片 item.onload = () => { //該圖片載入完成 num++ if (num === imgs.length) { //圖片都載入完成了 for (let i = om; i < list.length; i++) { //遍歷ul下的每個li if (i < cols) { //給第一行每個li設定left/top值 list[i].style.left = (width + teep) * i + 'px' list[i].style.top = teep + 'px' hh.push(list[i].offsetHeight + teep * 2) } else { //除了第一行剩下的li let minHeight = Math.min(...hh) //求出最小高度 let minIndex = hh.indexOf(minHeight) //求出最小高度的索引值 list[i].style.left = (width + teep) * minIndex + 'px' list[i].style.top = minHeight + 'px' hh[minIndex] = list[i].offsetHeight + minHeight + teep //將最小高度更新 } } om = list.length //更新排版完成數量 ul.style.height = ul.scrollHeight + 'px' //給ul設定高度 } } }) }) </script> </html>
複製以上程式碼,並把下面這一段js程式碼複製到js檔案中放到和上面程式碼同級的地方並引入,即可執行瀏覽效果
程式碼如下:
function ajax(obj, fn) { let ajx = new XMLHttpRequest() //建立ajax例項 obj.type = obj.type ? obj.type : 'get' //判斷type存不存在,不存在預設等於get let data = '' //向後端傳送的資料 if (obj.data) { //判斷是否存在 for (let i in obj.data) { data += i + '=' + obj.data[i] + '&' //鍵值拼接成name=zhagnsan&age=18形式 } let k = data.split('') k.splice(data.length - 1, 1) data = k.join('') } if (obj.type == 'get') { //處理get請求傳送資料 ajx.open(obj.type, obj.url + '?' + data) //地址上拼接資料 ajx.send() } else if (obj.type == 'post') { //處理post請求傳送資料 ajx.open(obj.type, obj.url) ajx.setRequestHeader('content-type', 'application/x-www-form-urlencoded') //設定請求頭 ajx.send(data) //傳送資料 } ajx.onreadystatechange = () => { if (ajx.readyState == 4) { if (ajx.status == 200) { /* 將得到的資料傳給回撥函式 短路寫法,如果不傳fn為空不會執行,有值就執行 */ fn && fn(ajx.responseText) } } } } // ajax({ //呼叫封裝的方法 // type: 'get', //可以不寫,預設get // url: 'http://localhost/day02/api/gouwu.php', //請求地址 // data: { //需要傳輸的資料,可選 // name: 'zhangsan', // age: 18 // } // },a=>{//處理的到的資料 // console.log(a) // }) function jsonp(obj) { let sc = document.createElement('script') let data = '' if (obj.data) { for (let i in obj.data) { data += `${i}=${obj.data[i]}&` } data = data.slice(0, -1) sc.setAttribute('src', obj.url + `?cd=${obj.cd}&${data}`) } else { sc.setAttribute('src', obj.url + `?cd=${obj.cd}`) } document.body.appendChild(sc) } // jsonp({ // url:'http://localhost/day02/api/gouwu.php', // cd:'fn' // },a=>{ // console.log(a) // }) function get(obj) { return new Promise((resolve, reject) => { let a = new XMLHttpRequest() let data = '' if (obj.data) { for (let i in obj.data) { data += i + '=' + obj.data[i] + '&' } data = data.slice(0, -1) a.open('get', obj.url + '?' + data) }else{ a.open('get', obj.url) } a.send() a.onreadystatechange = () => { if (a.readyState === 4) { if (a.status === 200) { resolve(a.responseText) } else { reject() } } } }) } // get({//呼叫格式 // url:'http://localhost/day02/api/gouwu.php',//獲取的地址 // data:{ //可不寫 // a:1, // b:2 // } // }).then(a=>{//獲取資料成功 // console.log(a) // }).catch(err=>{ //獲取資料失敗 // console.log(err) // })