大規模なデータを効率的にレンダリング「vue-virtual-collection」

by kabanoki

HTML

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/index.min.js"></script>
<div id="app">
  <select v-model="n">
    <option value="50">50</option>
    <option value="100">100</option>
    <option value="150">150</option>
    <option value="500">500</option>
    <option value="1000">1000</option>
  </select>
  <virtual-collection
      :cell-size-and-position-getter="cellSizeAndPositionGetter"
      :collection="items"
      :height="500"
      :width="680"
  >
      <div slot="cell" slot-scope="props">{{props.data}}</div>
  </virtual-collection>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>

CSS

.cell-container{
  border: 1px solid #ddd;
  justify-content: center;
  align-items: center;
  display: flex;
}

Vue

const VirtualCollection = window["vue-virtual-collection"].default;

Vue.use(VirtualCollection);

let app = new Vue({
  el: '#app',
  data: {
    n:1000,
    items: new Array(1000).fill(0).map((_, index) => ({ data: '#' + index }))
  },
  methods: {
    cellSizeAndPositionGetter(item, index) {
            // compute size and position
            let min = 100 ;
            let max = 150 ;
            let random = Math.floor(Math.random() * (max + 1 - min) ) + min ;

            return {
                width: 100,
                height: random,
                x: (index % 6) * 110,
                y: parseInt(index / 6) * 160
            }
        }
    },
    watch: {
      n: function(value) {
        this.items = new Array(Number(this.n)).fill(0).map((_, index) => ({ data: '#' + index }));
      }
    }
});