91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

基于Vue如何封裝一個虛擬列表組件

發布時間:2023-03-07 10:26:22 來源:億速云 閱讀:108 作者:iii 欄目:開發技術

今天小編給大家分享一下基于Vue如何封裝一個虛擬列表組件的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

    組件效果

    基于Vue如何封裝一個虛擬列表組件

    使用方法

    <template>
      <div>
        <div class="virtual-list-md-wrap">
          <hub-virtual-list :allData="data" itemHeight="70" :virtualData.sync="virtualData">
            <div v-for="(item, index) in virtualData" class="item">
             {{ item  }}
             <el-button type="primary" size="mini" plain @click="deleteItem(item)">刪除</el-button>
            </div>
          </hub-virtual-list>
        </div>
      </div>
      
    </template>
    <script>
    export default {
      data() {
        return {
          data: [],
          virtualData: []
        }
      },
      created() {
        setTimeout(() => {
          this.addData()
        }, 1000)
      },
      watch: {
      },
      methods: {
        addData() {
          for(let i = 0; i <= 100000; i ++) {
            this.$set(this.data, i, i)
          }
        },
        deleteItem(index) {
          this.data = this.data.filter((item) => item !== index)
        }
      }
    }
    </script>
    <style>
    .virtual-list-md-wrap {
      height: 500px;
      background-color: #FFFAF0;
    }
    .item {
      border-bottom: 1px solid #666;
      padding: 20px;
      text-align: center;
    }
    </style>

    屬性

    參數說明類型可選值默認值
    allData全部數據Array-[]
    virtualData虛擬數據Array-[]
    itemHeight每行的高度,用于計算滾動距離Number, String-30

    插槽

    插槽名說明
    -自定義默認內容,即主體區域

    封裝過程

    首先梳理我想要的組件效果:

    • 滾動條正常顯示

    • 加載渲染大量數據不卡頓

    • 能對列表數據進行操作增刪等

    滾動條正常顯示

    需要把顯示框分為3部分:顯示高度,全部高度,虛擬數據高度

    大概的比例是這樣的

    基于Vue如何封裝一個虛擬列表組件

    為達到滾動條的效果,在最外層顯示高度設置overflow: auto可以把滾動條撐出來,全部高度則設置position: absolute;z-index: -1;height: auto;,虛擬數據高度則設置position: absolute; height: auto;

    整體樣式代碼如下

    <template>
      <div class="hub-virtual-list">
        <!-- 顯示高度 -->
        <div ref="virtualList" class="hub-virtual-list-show-height" @scroll="scrollEvent($event)">
          <!-- 全部高度,撐出滾動條 -->
          <div class="hub-virtual-list-all-height" :/>
          <!-- 存放顯示數據 -->
          <div class="virtual-list" :/>
        </div>
      </div>
    </template>
    
    <style lang="scss" scoped>
    .hub-virtual-list {
      height: 100%;
      &-show-height {
        position: relative;
        overflow: auto;
        height: 100%;
        -webkit-overflow-scrolling: touch;
      }
      &-all-height {
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        z-index: -1;
        height: auto;
      }
      .virtual-list {
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        height: auto;
      }
    }
    </style>

    加載渲染大量數據不卡頓

    如果想要渲染不卡頓,就得只加載顯示區域的虛擬數據,虛擬數據的更新邏輯為:用startIndexendIndex標志虛擬數據的起始索引和結束索引,在滾動條滑動時,通過計算滑動的距離去更新startIndexendIndex。另外用offset標記偏移量,對虛擬數據區域設置transform: translate3d(0, ${this.offset}px, 0)跟著滾動條去移動

    核心部分代碼如下

    scrollEvent(e) {
      const scrollTop = this.$refs.virtualList.scrollTop
      // 起始索引 = 滾動距離 / 每項高度
      this.startIndex = Math.floor(scrollTop / this.itemHeight)
      // 結束索引 = 開始索引 + 可見數量
      this.endIndex = this.startIndex + this.visibleCount
      // 偏移量 = 滾動距離
      this.offset = scrollTop - (scrollTop % this.itemHeight)
    }

    能對列表數據進行操作增刪等

    如果想要在數據里添加操作按鈕,則需要在封裝組件時設置插槽,且需要把虛擬數據同步給父組件

    設置插槽

    <!-- 顯示高度 -->
    <div ref="virtualList" class="hub-virtual-list-show-height" @scroll="scrollEvent($event)">
      <!-- 全部高度,撐出滾動條 -->
      <div class="hub-virtual-list-all-height" :/>
      <!-- 存放顯示數據 -->
      <div class="virtual-list" :>
        <!-- 設置插槽 -->
        <slot/> 
      </div>
    </div>

    滾動時把虛擬數據同步給父組件

    scrollEvent(e) {
      const scrollTop = this.$refs.virtualList.scrollTop
      // 起始索引 = 滾動距離 / 每項高度
      this.startIndex = Math.floor(scrollTop / this.itemHeight)
      // 結束索引 = 開始索引 + 可見數量
      this.endIndex = this.startIndex + this.visibleCount
      // 偏移量 = 滾動距離
      this.offset = scrollTop - (scrollTop % this.itemHeight)
      // 同步父組件數據
      this.inVirtualData = this.allData.slice(this.startIndex, this.endIndex)
      this.$emit('update:virtualData', this.inVirtualData)
    }

    完整代碼

    <template>
      <div class="hub-virtual-list">
        <!-- 顯示高度 -->
        <div ref="virtualList" class="hub-virtual-list-show-height" @scroll="scrollEvent($event)">
          <!-- 全部高度,撐出滾動條 -->
          <div class="hub-virtual-list-all-height" :/>
          <!-- 存放顯示數據 -->
          <div class="virtual-list" >
            <slot/>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      name: 'hub-virtual-list',
      props: {
        // 全部數據
        allData: {
          type: Array,
          default: () => []
        },
        // 虛擬數據
        virtualData: {
          type: Array,
          default: () => []
        },
        // 每項高度
        itemHeight: {
          type: [Number, String],
          default: '30'
        },
        // 每項樣式
        itemStyle: {
          type: Object,
          default: () => {}
        }
      },
      data() {
        return {
          // 起始索引
          startIndex: 0,
          // 結束索引
          endIndex: null,
          // 偏移量,計算滾動條
          offset: 0,
          inVirtualData: []
        }
      },
      computed: {
        // 所有高度
        allHeight() {
          // 每項高度 * 項數
          return this.itemHeight * this.allData.length
        },
        // 可見數量
        visibleCount() {
          // 可見高度 / 每項高度
          return Math.ceil(this.showHeight / this.itemHeight)
        },
        // 顯示數據的偏移量
        getTransform() {
          return `translate3d(0, ${this.offset}px, 0)`
        }
      },
      watch: {
        allData: {
          handler() {
            this.inVirtualData = this.allData.slice(this.startIndex, this.endIndex)
            this.$emit('update:virtualData', this.inVirtualData)
          },
          deep: true
        }
      },
      mounted() {
        this.showHeight = this.$el.clientHeight
        this.startIndex = 0
        this.endIndex = this.startIndex + this.visibleCount
      },
      methods: {
        scrollEvent(e) {
          const scrollTop = this.$refs.virtualList.scrollTop
          // 起始索引 = 滾動距離 / 每項高度
          this.startIndex = Math.floor(scrollTop / this.itemHeight)
          // 結束索引 = 開始索引 + 可見數量
          this.endIndex = this.startIndex + this.visibleCount
          // 偏移量 = 滾動距離
          this.offset = scrollTop - (scrollTop % this.itemHeight)
          // 同步父組件數據
          this.inVirtualData = this.allData.slice(this.startIndex, this.endIndex)
          this.$emit('update:virtualData', this.inVirtualData)
        }
      }
    }
    </script>
    
    <style lang="scss" scoped>
    .hub-virtual-list {
      height: 100%;
      &-show-height {
        position: relative;
        overflow: auto;
        height: 100%;
        -webkit-overflow-scrolling: touch;
      }
      &-all-height {
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        z-index: -1;
        height: auto;
      }
      .virtual-list {
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        height: auto;
      }
    }
    </style>

    以上就是“基于Vue如何封裝一個虛擬列表組件”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    vue
    AI

    呼图壁县| 天津市| 新源县| 威宁| 开江县| 乐昌市| 南平市| 长武县| 大方县| 崇礼县| 金塔县| 固镇县| 蒲江县| 北京市| 丹阳市| 六枝特区| 神池县| 宜阳县| 曲靖市| 砚山县| 文安县| 黑龙江省| 望城县| 东兰县| 西平县| 铜梁县| 沙湾县| 筠连县| 永福县| 巩义市| 永康市| 乌兰浩特市| 拜城县| 丰顺县| 鄂伦春自治旗| 阜南县| 油尖旺区| 治县。| 赤峰市| 浠水县| 皋兰县|