SOURCE

console 命令行工具 X clear

                    
>
console
const ListView = {
	name: 'ListView',
    template: '#list-template',
	props: {
  	data: {
      type: Array,
      required: true
    },
    itemSizeGetter: {
      type: Function
    }
  },
  
  computed: {
    contentHeight() {
      const { data, itemSizeGetter } = this;
      let total = 0;
      for (let i = 0, j = data.length; i < j; i++) {
        total += itemSizeGetter.call(null, data[i], i);
      }
      return total;
    }
  },

  mounted() {
    this.updateVisibleData();
  },

  data() {
    return {
      visibleData: [],
      index:1
    };
  },

  methods: {
  	getItemSizeAndOffset(index) {
    	const { data, itemSizeGetter } = this;
      let total = 0;
      for (let i = 0, j = Math.min(index, data.length - 1); i <= j; i++) {
        const size = itemSizeGetter.call(null, data[i], i);
        
        if (i === j) {
          return {
            offset: total,
            size
          };
        }
        total += size;
      }

      return {
        offset: 0,
        size: 0
      };
    },

  	findNearestItemIndex(scrollTop) {
      const { data, itemSizeGetter } = this;
      let total = 0;
      for (let i = 0, j = data.length; i < j; i++) {
        const size = itemSizeGetter.call(null, data[i], i);//这个方法需要自己写  获取第N个滑块高度赋值给size
        total += size;
        if (total >= scrollTop || i === j -1) {
          return i;
        }
      }

      return 0;
    },

  	updateVisibleData(scrollTop) {
    	scrollTop = scrollTop || 0;
      const start = this.findNearestItemIndex(scrollTop);
      const end = this.findNearestItemIndex(scrollTop + this.$refs.list.clientHeight);
      this.visibleData = this.data
      console.log(start)
      //假设以start索引位置为分割   用索引位置来判断是否在当前选项
      if(start>0){
          this.index=1
      }
      if(start>1000){
          this.index=2
      }
      if(start>2000){
          this.index=3
      }
      if(start>3000){
          this.index=4
      }
      //下面的是虚拟列表实现  不需要可以屏蔽
      this.visibleData = this.data.slice(start, Math.min(end + 1, this.data.length));
      this.$refs.content.style.webkitTransform = `translate3d(0, ${ this.getItemSizeAndOffset(start).offset }px, 0)`;
    },

    handleScroll() {
      const scrollTop = this.$refs.list.scrollTop;
      this.updateVisibleData(scrollTop);
    }
  }
};

new Vue({
  components: {
  	ListView
  },
  
  methods: {
  	itemSizeGetter(item) {
    	return 30 + item.value % 10;
    }
  },

  data() {
    const data = [];
    for (let i = 0; i < 10000; i++) {
      data.push({ value: i });
    }

    return {
      data
    };
  }
}).$mount('#app')
<script type="text/x-template" id="list-template">
<div>
 <ul class="list-view-right">
  <li :class="{isActive:index===item}" v-for="item in 4">{{item}}</li>
 </ul>
 <div 
    class="list-view" 
    ref="list" 
    @scroll="handleScroll">
    <div     
      class="list-view-phantom"       
      :style="{
         height: contentHeight + 'px'
      }">
    </div>
    <div
      ref="content"
      class="list-view-content">
      <div
        class="list-view-item"
        :style="{
          height: itemSizeGetter(item) + 'px'
        }"
        :key="index"
        v-for="(item, index) in visibleData">
        {{ item.value }}
      </div>
    </div>
  </div>
 </div>
  
</script>
<div id="app">
<template>
  <list-view 
    :item-size-getter="itemSizeGetter"
    :estimated-item-size="30"  
    :data="data"></list-view>
</template>
</div>
.list-view {
  height: 400px;
  overflow: auto;
  position: relative;
  border: 1px solid #666;
}
.list-view-right{
    float: left;
}
.list-view-phantom {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  z-index: -1;
}

.list-view-content {
  left: 0;
  right: 0;
  top: 0;
  position: absolute;
}

.list-view-item {
  padding: 5px;
  color: #666;
  height: 30px;
  line-height: 30px;
  box-sizing: border-box;
  border:1px solid red;
}
.isActive{
    color:red;
}

本项目引用的自定义外部资源