2
0
mirror of https://github.com/tenrok/vue-select.git synced 2026-05-17 02:29:37 +03:00

add tutorial on working with large datasets

This commit is contained in:
Jeff
2019-11-16 15:25:42 -08:00
parent 8794696e92
commit dac09bc153
6 changed files with 164 additions and 0 deletions
+116
View File
@@ -0,0 +1,116 @@
<template>
<div class="flex">
<div class="airport-select default">
<table>
<tr>
<th colspan="2">Without Optimization 😬</th>
</tr>
<tr>
<td>Dropdown Render</td>
<td :class="{ slow: !! timing.default }">{{ timing.default }}ms</td>
</tr>
</table>
<observed-select
data-type="default"
placeholder="Search for a destination..."
:options="options"
:get-option-label="({icao, name}) => `${icao} - ${name}`"
></observed-select>
</div>
<div class="airport-select optimized">
<table>
<tr>
<th colspan="2">With Optimization 🤓</th>
</tr>
<tr>
<td>Dropdown Render</td>
<td :class="{ fast: !! timing.optimized }">{{ timing.optimized }}ms</td>
</tr>
</table>
<observed-select
data-type="optimized"
placeholder="Search for a destination..."
:options="options"
:filter="filter"
:loading="loading"
:get-option-label="({icao, name}) => `${icao} - ${name}`"
></observed-select>
</div>
</div>
</template>
<script>
import Vue from 'vue';
import airports from 'airport-data';
import vSelect from '../../../src/components/Select'
const timings = Vue.observable({
optimized: 0,
default: 0
});
const ObservedSelect = {...vSelect};
ObservedSelect.watch.dropdownOpen = function (open) {
if (open) {
const start = performance.now();
this.$nextTick(() => {
timings[this.$el.dataset.type] = performance.now() - start;
})
}
};
export default {
name: "AirportCodes",
components: {ObservedSelect},
data: () => ({loading: false}),
methods: {
filter (airports, search) {
if (search.length === 0) {
return airports.slice(0, 50);
}
return airports.filter(airport => {
const keys = ['name', 'city', 'country', 'iata', 'icao'];
return keys.some(key => String(airport[key]).toLowerCase().includes(search.toLowerCase()))
}).slice(0, 50);
}
},
computed: {
options: () => airports,
timing: () => timings,
}
}
</script>
<style scoped>
table {
display: table;
width: 100%;
}
.flex {
display: flex;
}
.airport-select {
width: 50%;
}
.airport-select + .airport-select {
margin-left: 1rem;
}
.fast,
.slow {
font-weight: bold;
}
.slow {
color: red;
}
.fast {
color: #3eaf7c;
}
</style>
+1
View File
@@ -122,6 +122,7 @@ module.exports = {
['guide/vuex', 'Vuex'],
['guide/ajax', 'AJAX'],
['guide/loops', 'Using in Loops'],
['guide/bigdata', 'Large Datasets'],
],
},
{
+3
View File
@@ -1,6 +1,9 @@
import vSelect from '../../src/components/Select';
export default ({Vue, options, router, siteData}) => {
// Vue.config.performance = true;
Vue.config.devtools = true;
Vue.component('v-select', vSelect);
/**
+38
View File
@@ -0,0 +1,38 @@
# Working with Big Datasets
When your `options` array gets into the thousands, you will start to see performance dip. If you
have 2,000 options, you have 2,000 dom nodes being rendered into the dropdown. It's very difficult
to render that many nodes at once and maintain 60fps in the browser.
Regardless of whether your options are primitives or objects, the performance hit comes from
rendering their text labels (or slot) to the dom. The path to keeping things snappy is then to limit
the amount of nodes that get rendered to the dropdown.
## Optimized Filtering
You can optimize performance by tweaking Vue Select's filtering and implementing it yourself.
Consider a list of airport codes with roughly ~7,500 entries. Rendering out 7,500 airports doesn't
actually help the user much, they're just looking for one in particular.
<AirportCodes />
The only difference between these two examples is the `filter` prop. Here's the `filter` for the
optimized example:
```js
filter (airports, search) {
if (search.length === 0) {
return airports.slice(0, 50);
}
return airports.filter(airport => {
const keys = ['name', 'city', 'country', 'iata', 'icao'];
return keys.some(key => String(airport[key]).toLowerCase().includes(search.toLowerCase()))
}).slice(0, 50);
}
```
If there's no search text, we only display the first 50 options. If there is a search query, we'll
check if any keys on the object include the search string. Again, we'll limit this to 50 options.
The key to have Vue Select perform well with thousands of options is to limit the number of options
that are displayed to the end user, without hindering their ability to select the right option.
+1
View File
@@ -14,6 +14,7 @@
"@vuepress/plugin-pwa": "^1.0.0-alpha.47",
"@vuepress/plugin-register-components": "^1.0.0-alpha.47",
"@vuepress/plugin-search": "^1.0.0-alpha.47",
"airport-data": "^1.0.1",
"cross-env": "^5.2.0",
"fuse.js": "^3.4.4",
"gh-pages": "^0.11.0",
+5
View File
@@ -1161,6 +1161,11 @@ agentkeepalive@^2.2.0:
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-2.2.0.tgz#c5d1bd4b129008f1163f236f86e5faea2026e2ef"
integrity sha1-xdG9SxKQCPEWPyNvhuX66iAm4u8=
airport-data@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/airport-data/-/airport-data-1.0.1.tgz#41c743c48fc5b37765a1bd3cf0617c1de8151316"
integrity sha1-QcdDxI/Fs3dlob088GF8HegVExY=
ajv-errors@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"