瀑布流程式碼實現及思路

王東煜發表於2019-10-09
思路:/*
        1.獲取資料:封裝成一個函式,去實現獲取資料的動作
        2.渲染資料:把從後臺獲取到的資料展示到頁面上,按照列展示的,迴圈後臺給的陣列,
          然後把每一條資料拼接好,新增到長度最小的一列,這裡封裝了一個最小列的方法,
          把元素集合轉成陣列,然後按照clientHeight 進行排序,由此找到最低那個li.
        3.實現滾動載入更多資料,當長度最小的那個li的底部漏出時就載入新的資料,loadmore
          為了,防止一次性請求多次,多了一個flag判斷,只有當flag為false時,才去執行新資料請求載入
          當請求開始時  flag設定為true 渲染成功,我們把flag再設定為false。
        4.實現圖片懶載入的操作,loadImg loadAll當圖片還沒有出現在可視視窗的時候不去載入圖片,只有當圖片漏出來一半時再去載入
        5.預載入 ,當圖片要在展示成真正的圖片時 先用預設圖展示,然後在利用js建立一個臨時的圖片。
          讓這個臨時的圖片去 請求遠端 真實的圖片, 當請求成功後再把真實圖片地址賦給頁面的那個img標籤。 
        6.fadeIn:實現圖片的漸現,利用定時器對img進行opacity的累加操作 
    
        效能優化:每一個圖表對應一個div,會有但bug,優化成 所有圖示對應一個div 控制div中的內容
    
        */
        
     let body = document.getElementsByClassName('body')[0],
    olis = document.querySelectorAll('.body li'),
    oImg = body.getElementsByTagName('img')
let flag = false;//代表新資料渲染完成 什麼時候 flag應該是個true ??//新資料一請求,就把 flag 變 
let n = 0;

//獲取資料
function getData() {
    flag = true;
    n++;
    let xhr = new XMLHttpRequest();
    xhr.open('get', './data.json', true);
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && /200|304/.test(xhr.status)) {//請求成功
            console.log(JSON.parse(xhr.response))
            let data = JSON.parse(xhr.response)
            render(data)//獲取新資料 渲染頁面
            flag = false;//新資料渲染完成後的操作
            loadAll();
        }
    }
    xhr.send();
}
getData();


function render(data) {
    //data 後臺給的陣列
    //迴圈陣列 拼接字串 拼接好的字串放進頁面
    let str = '';
    data.forEach(item => {
        let { pic, author, desc, height } = item
        // str = `
        //     <div class="img_box">
        //         <img realSrc="${pic}" realSrc="./img/1.jpg" alt="" style='height:${height}px'>
        //         <P class="desc">${desc}</P>
        //         <p class="author">${author}</p> 
        //     </div>`
        // //str是新拼接出來的一個快,我們需要決定的事 這個快放在哪個li中
        // // olis[index % 5].innerHTML += str;
        // let temp = getMinLi();//找出最短li
        // //把要增加的這一項放到最低的li中
        // temp.innerHTML += str;
        str = `
            <img realSrc="${pic}" realSrc="./img/1.jpg" alt="" style='height:${height}px'>
            <P class="desc">${desc}</P>
             <p class="author">${author}</p> 
            `
        let temp = getMinLi();//找出最短li
        let div = document.createElement('div')
        div.className = 'img_box';
        div.innerHTML = str;
        temp.appendChild(div);
    })
}

//找最短的li
function getMinLi() {
    //找最短的li
    let ary = [...olis].sort((a, b) => {
        return a.clientHeight - b.clientHeight;
    })
    return ary[0];
}

//第三部 滾動載入新資料

window.onscroll = function () {
    loadMore()
    loadAll()
}

function loadMore() {
    //最短的那個li漏出底部的時候 就載入新資料
    if (n >= 3) return;//滑動滾輪載入兩次圖片,如果不設定就無限載入
    let li = this.getMinLi();
    if (this.utils.offset(li).t + li.clientHeight <= document.documentElement.scrollTop + this.utils.winH().h) {
        //需要等新資料渲染到頁面後 再去載入新資料
        if (!flag) {
            console.log(666)
            getData();
        }

    }
}
function loadAll() {
    [...oImg].forEach(item => {
        loadImg(item)
    })
}


function loadImg(ele) {
    if (ele.myLoad) return
    //懶載入
    if (utils.offset(ele).t + ele.clientHeight / 2 <= document.documentElement.scrollTop + utils.winH().h) {
        //圖片漏出來一半
        let realSrc = ele.getAttribute('realSrc');
        // ele.src = realSrc;
        let temp = new Image();
        temp.src = realSrc;//讓臨時圖片去請求真實的圖片地址
        temp.onload = function () {
            //圖片從遠端拿到了本地
            ele.src = realSrc;
            ele.myLoad = true;//載入過之後就不再載入
            fadeIn(ele)
        }
        temp = null;
    }
}


//預載入
function fadeIn(ele) {
    ele.style.opacity = 0;
    let n = 0;
    ele.timer = setInterval(() => {
        n += 0.01;
        if (n >= 1) {
            n = 1;
            clearInterval(ele.timer)
        }
        ele.style.opacity = n;
    }, 10)
}   

//具體程式碼如下
https://github.com/wdy15632628358/zhengshike2/blob/master/19-10/week4/day1/%E7%80%91%E5%B8%83%E6%B5%81.zip
複製程式碼

相關文章