|
| 1 | +<script src="../../dist/vue.js"></script> |
| 2 | +<link rel="stylesheet" href="style.css"> |
| 3 | +<link rel="stylesheet" href="demo.css"> |
| 4 | + |
| 5 | +<div id="el"> |
| 6 | + <h1> |
| 7 | + Rendering Large Datasets With Vue {{renderTime}} |
| 8 | + </h1> |
| 9 | + |
| 10 | + <form> |
| 11 | + <strong>Filter Data</strong>: |
| 12 | + <input type="text" v-model="filter"> |
| 13 | + |
| 14 | + <!-- |
| 15 | + If the user is filtering the data, we want to offer some insight into |
| 16 | + the breadth of the filtering. |
| 17 | + --> |
| 18 | + <span v-if="filter"> |
| 19 | + — |
| 20 | + Filtering <strong>{{ filter }}</strong> |
| 21 | + over {{ dataPoints }} data points, |
| 22 | + {{ visibleCount() }} found. |
| 23 | + </span> |
| 24 | + |
| 25 | + <!-- Provide tooling to unmount and remount the grid. --> |
| 26 | + <!-- <a v-if="grid.length" v-on="click:unmountGrid">Unmount Grid</a> --> |
| 27 | + <a @click="remountGrid">Remount Grid</a> |
| 28 | + </form> |
| 29 | + |
| 30 | + <table width="100%" cellspacing="2" :class="{ filtered: filter }"> |
| 31 | + <tr v-for="row in grid"> |
| 32 | + <th>{{ row.id }}</th> |
| 33 | + <td v-for="item in row.items" |
| 34 | + class="item" |
| 35 | + :class="{ hidden: !matches(item) }"> |
| 36 | + {{ item.value }} |
| 37 | + </td> |
| 38 | + </tr> |
| 39 | + </table> |
| 40 | +</div> |
| 41 | + |
| 42 | +<script> |
| 43 | +function generateGrid( rowCount, columnCount ) { |
| 44 | + var valuePoints = [ |
| 45 | + "Daenerys", "Jon", "Sansa", "Arya", "Stannis", "Gregor", "Tyrion", |
| 46 | + "Theon", "Joffrey", "Ramsay", "Cersei", "Bran", "Margaery", |
| 47 | + "Melisandre", "Daario", "Jamie", "Eddard", "Myrcella", "Robb", |
| 48 | + "Jorah", "Petyr", "Tommen", "Sandor", "Oberyn", "Drogo", "Ygritte" |
| 49 | + ]; |
| 50 | + var valueIndex = 0; |
| 51 | + var grid = []; |
| 52 | + |
| 53 | + for ( var r = 0 ; r < rowCount ; r++ ) { |
| 54 | + var row = { |
| 55 | + id: r, |
| 56 | + items: [] |
| 57 | + }; |
| 58 | + for ( var c = 0 ; c < columnCount ; c++ ) { |
| 59 | + row.items.push({ |
| 60 | + id: ( r + "-" + c ), |
| 61 | + value: valuePoints[ valueIndex ] |
| 62 | + }); |
| 63 | + if ( ++valueIndex >= valuePoints.length ) { |
| 64 | + valueIndex = 0; |
| 65 | + } |
| 66 | + } |
| 67 | + grid.push( row ); |
| 68 | + } |
| 69 | + |
| 70 | + return( grid ); |
| 71 | +} |
| 72 | + |
| 73 | +var grid = generateGrid(1000, 10) |
| 74 | +var s = window.performance.now() |
| 75 | +console.profile('a') |
| 76 | +var vm = new Vue({ |
| 77 | + |
| 78 | + el: '#el', |
| 79 | + |
| 80 | + data: { |
| 81 | + renderTime: 0, |
| 82 | + grid: Object.freeze(grid), |
| 83 | + dataPoints: grid.length * grid[0].items.length, |
| 84 | + filter: '' |
| 85 | + }, |
| 86 | + |
| 87 | + methods: { |
| 88 | + updateFilter (e) { |
| 89 | + this.filter = e.target.value.toLowerCase() |
| 90 | + }, |
| 91 | + matches (item) { |
| 92 | + return item.value.toLowerCase().indexOf(this.filter) > -1 |
| 93 | + }, |
| 94 | + visibleCount () { |
| 95 | + var count = 0 |
| 96 | + var grid = this.grid |
| 97 | + for (var i = 0, l = grid.length; i < l; i++) { |
| 98 | + var row = grid[i].items |
| 99 | + for (var j = 0, k = row.length; j < k; j++) { |
| 100 | + var item = row[j] |
| 101 | + var matched = !this.filter || this.matches(item) |
| 102 | + if (matched) { |
| 103 | + count++ |
| 104 | + } |
| 105 | + } |
| 106 | + } |
| 107 | + return count |
| 108 | + }, |
| 109 | + unmountGrid: function () { |
| 110 | + this.grid = [] |
| 111 | + }, |
| 112 | + remountGrid: function () { |
| 113 | + this.grid = generateGrid(1000, 10) |
| 114 | + console.profile('unmount') |
| 115 | + Vue.nextTick(function () { |
| 116 | + console.profileEnd('unmount') |
| 117 | + }) |
| 118 | + } |
| 119 | + } |
| 120 | +}) |
| 121 | +console.profileEnd('a') |
| 122 | +setTimeout(function () { |
| 123 | + vm.renderTime = window.performance.now() - s |
| 124 | +}, 0) |
| 125 | +</script> |
0 commit comments