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:
@@ -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>
|
||||
@@ -122,6 +122,7 @@ module.exports = {
|
||||
['guide/vuex', 'Vuex'],
|
||||
['guide/ajax', 'AJAX'],
|
||||
['guide/loops', 'Using in Loops'],
|
||||
['guide/bigdata', 'Large Datasets'],
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user