真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

vue如何實(shí)現(xiàn)虛擬滾動(dòng)

本文小編為大家詳細(xì)介紹“vue如何實(shí)現(xiàn)虛擬滾動(dòng)”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“vue如何實(shí)現(xiàn)虛擬滾動(dòng)”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來(lái)學(xué)習(xí)新知識(shí)吧。

創(chuàng)新互聯(lián)公司成立于2013年,先為鳳陽(yáng)等服務(wù)建站,鳳陽(yáng)等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為鳳陽(yáng)企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。

效果:

vue如何實(shí)現(xiàn)虛擬滾動(dòng)

滾動(dòng)原理

為了理解虛擬滾動(dòng)的實(shí)現(xiàn)原理,首先觀察下面圖片.手指向下滑動(dòng)時(shí),HTML頁(yè)面也會(huì)隨之向上滾動(dòng).
通過(guò)圖片標(biāo)記的距離,我們可以得出這樣的結(jié)論.當(dāng)屏幕視口的上邊沿和id為item的div元素上邊沿重合時(shí),item元素距離長(zhǎng)列表頂部的距離剛好等于頁(yè)面的滾動(dòng)距離scrollTop(這個(gè)結(jié)論會(huì)在后面計(jì)算距離時(shí)用到).

虛擬滾動(dòng)為了模擬出逼真的滾動(dòng)效果,首先應(yīng)該滿足以下兩個(gè)要求.

vue如何實(shí)現(xiàn)虛擬滾動(dòng)

  • 虛擬滾動(dòng)列表的滾動(dòng)條和普通列表保持一致.比如列表包含1000條數(shù)據(jù),當(dāng)瀏覽器使用普通渲染的方式,假設(shè)滾動(dòng)條需要向下滾動(dòng)5000px才能貼底.那么應(yīng)用虛擬滾動(dòng)技術(shù)后,滾動(dòng)條也應(yīng)該保證具備相同的特征,向下滾動(dòng)5000px才能貼底.

  • 虛擬滾動(dòng)只會(huì)渲染視口以及上下兩側(cè)的部分Dom元素.隨著滾動(dòng)條往下滑動(dòng),視圖的內(nèi)容要實(shí)時(shí)更新,保證同普通渲染長(zhǎng)列表時(shí),看到的內(nèi)容一致.

為了滿足上面的要求,html設(shè)計(jì)結(jié)構(gòu)如下.

.wrapper是最外層的容器元素,position設(shè)置成absolute或relative,子元素依據(jù)它做定位.

子元素.background和.list是實(shí)現(xiàn)虛擬滾動(dòng)的關(guān)鍵..background是一個(gè)空的div,但它需要設(shè)置高度,高度值等于長(zhǎng)列表所有列表項(xiàng)高度相加的總和.另外還要將其設(shè)置成絕對(duì)定位,z-index的值置為-1.

.list內(nèi)部負(fù)責(zé)動(dòng)態(tài)渲染視口觀察到的Dom元素,position設(shè)置成absolute.



.wrapper {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  top: 60px;
  overflow-y: scroll;
  .background {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: -1;
  }
  .list {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
  }
}

假如上面代碼total_height等于10000px,頁(yè)面運(yùn)行效果圖如下所示.
由于子元素.background設(shè)置了高度,父元素.wrapper就會(huì)被子元素支撐起來(lái),同時(shí)會(huì)出現(xiàn)滾動(dòng)條.
如果此時(shí)向下滑動(dòng),兩個(gè)子元素.background和.list會(huì)同時(shí)向上滾動(dòng).當(dāng)滾動(dòng)距離達(dá)到了9324px,滾動(dòng)條也抵達(dá)了底部.
這是因?yàn)楦冈?wrapper本身高度為676px,加上滑動(dòng)距離9324px,結(jié)果就剛好等于列表總高度10000px.
通過(guò)觀察以上行為可知,.background雖然只是一個(gè)空的div,但是通過(guò)給它賦予列表的總高度,可以讓右側(cè)的滾動(dòng)條和普通長(zhǎng)列表渲染產(chǎn)生的滾動(dòng)條保持外觀和行為上一致.

vue如何實(shí)現(xiàn)虛擬滾動(dòng)

滾動(dòng)條的問(wèn)題解決了,但隨著滾動(dòng)條往下滑,數(shù)據(jù)列表隨之上移,列表全部移出了屏幕之后,接下來(lái)的滑動(dòng)全是白屏.
為了解決白屏問(wèn)題,視口必須始終展現(xiàn)出滑動(dòng)的數(shù)據(jù).那么.list元素要根據(jù)滑動(dòng)的距離動(dòng)態(tài)更新自身絕對(duì)定位的top值,這樣就能確保.list不被劃出屏幕之外.同時(shí)還要依據(jù)滑動(dòng)的距離動(dòng)態(tài)渲染當(dāng)前視口應(yīng)該展示的數(shù)據(jù).

觀察下面動(dòng)效圖,右側(cè)Dom結(jié)構(gòu)展示了滑動(dòng)時(shí)的變化.

滾動(dòng)條往下快速滑動(dòng)后,列表的Dom元素快速渲染刷新.此時(shí)除了.list內(nèi)部的Dom元素不斷的更換,.list元素自身也在不斷修改transform: translate3d(0, ? px ,0)樣式值(修改translate3d能達(dá)到和修改top屬性值相似的效果).

vue如何實(shí)現(xiàn)虛擬滾動(dòng)

經(jīng)過(guò)上面的講解,虛擬滾動(dòng)的實(shí)現(xiàn)邏輯已經(jīng)清晰.首先js監(jiān)聽(tīng)滾動(dòng)條的滑動(dòng)事件,再通過(guò)滑動(dòng)距離計(jì)算出.list元素要渲染哪些子元素,其次更新.list元素位置.滾動(dòng)條不斷滑動(dòng)時(shí),子元素和位置也不斷更新,視口上便模擬出了滾動(dòng)效果.

實(shí)現(xiàn)

開(kāi)發(fā)的Demo頁(yè)面如下圖所示.列表項(xiàng)包含了以下三種結(jié)構(gòu):

  • 小型列表項(xiàng),城市首字母單獨(dú)成一行,高度為50px;

  • 普通列表項(xiàng),左側(cè)英文名,右側(cè)中文名,高度為100px;

  • 大型列表項(xiàng),左側(cè)英文名,中間中文名,右側(cè)一張圖片,高度為150px;

列表數(shù)據(jù)city_data的json結(jié)構(gòu)類似如下,type為1代表采用小型列表項(xiàng)的樣式結(jié)構(gòu)渲染,2代表普通列表項(xiàng),3代表大型列表項(xiàng).

[{"name":"A","value":"","type":1},{"name":"Al l'Ayn","value":"艾因","type":2},{"name":"Aana","value":"阿納","type":3} ... ]

vue如何實(shí)現(xiàn)虛擬滾動(dòng)

city_data包含了長(zhǎng)列表的所有數(shù)據(jù),city_data獲取后先遍歷調(diào)整每一項(xiàng)的數(shù)據(jù)結(jié)構(gòu)(代碼如下).

通過(guò)以下方法處理,每一個(gè)列表項(xiàng)最終都包含一個(gè)top和height值.top表示該項(xiàng)距離長(zhǎng)列表頂部的長(zhǎng)度,而height值指該項(xiàng)的高度.
total_height即整個(gè)列表的總高度,最終要賦予上文提及的.background元素.處理完后的數(shù)據(jù)賦予this.list存儲(chǔ),并記錄下最小列表項(xiàng)的高度this.min_height.

  mounted () {
     function getHeight (type) { // 根據(jù) type 值返回高度
        switch (type) {
          case 1: return 50;
          case 2: return 100;
          case 3: return 150;
          default:
            return "";
        }
      }
      let total_height = 0;
      const list = city_data.map((data, index) => {
        const height = getHeight(data.type);
        const ob = {
          index,
          height,
          top: total_height,
          data
        }
        total_height += height;
        return ob;
      })
      this.total_height = total_height; //  列表總高度
      this.list = list;
      this.min_height = 50; // 最小高度是50
      //屏幕最大能容納的列表項(xiàng)數(shù)量,containerHeight是父容器高度,按照最小高度來(lái)計(jì)算
      this.maxNum = Math.ceil(containerHeight / this.min_height);
  }

html根據(jù)type值渲染不同的樣式結(jié)構(gòu)(代碼如下).父容器.wrapper綁定一個(gè)滑動(dòng)事件onScroll,列表元素.list內(nèi)部不是遍歷this.list數(shù)組,因?yàn)閠his.list是原始數(shù)據(jù),包含了所有的列表項(xiàng).