Line 0
Link Here
|
0 |
- |
1 |
<template> |
|
|
2 |
<v-select |
3 |
:options="paginated" |
4 |
:filterable="false" |
5 |
@open="onOpen" |
6 |
@close="onClose" |
7 |
@search="query => (search = query)" |
8 |
> |
9 |
<template #list-footer> |
10 |
<li v-show="hasNextPage" ref="load" class="loader"> |
11 |
Loading more options... |
12 |
</li> |
13 |
</template> |
14 |
</v-select> |
15 |
</template> |
16 |
|
17 |
<script> |
18 |
export default { |
19 |
name: "InfiniteScroll", |
20 |
data() { |
21 |
const data = Array.apply(null, Array(200)).map((x, i) => { |
22 |
return `Country ${i}` |
23 |
}) |
24 |
return { |
25 |
observer: null, |
26 |
limit: 10, |
27 |
search: "", |
28 |
countries: data, |
29 |
} |
30 |
}, |
31 |
computed: { |
32 |
filtered() { |
33 |
return this.countries.filter(country => |
34 |
country.includes(this.search) |
35 |
) |
36 |
}, |
37 |
paginated() { |
38 |
return this.filtered.slice(0, this.limit) |
39 |
}, |
40 |
hasNextPage() { |
41 |
return this.paginated.length < this.filtered.length |
42 |
}, |
43 |
}, |
44 |
mounted() { |
45 |
/** |
46 |
* You could do this directly in data(), but since these docs |
47 |
* are server side rendered, IntersectionObserver doesn't exist |
48 |
* in that environment, so we need to do it in mounted() instead. |
49 |
*/ |
50 |
this.observer = new IntersectionObserver(this.infiniteScroll) |
51 |
}, |
52 |
methods: { |
53 |
async onOpen() { |
54 |
if (this.hasNextPage) { |
55 |
await this.$nextTick() |
56 |
this.observer.observe(this.$refs.load) |
57 |
} |
58 |
}, |
59 |
onClose() { |
60 |
this.observer.disconnect() |
61 |
}, |
62 |
async infiniteScroll([{ isIntersecting, target }]) { |
63 |
if (isIntersecting) { |
64 |
const ul = target.offsetParent |
65 |
const scrollTop = target.offsetParent.scrollTop |
66 |
this.limit += 10 |
67 |
await this.$nextTick() |
68 |
ul.scrollTop = scrollTop |
69 |
} |
70 |
}, |
71 |
}, |
72 |
} |
73 |
</script> |
74 |
|
75 |
<style scoped> |
76 |
.loader { |
77 |
text-align: center; |
78 |
color: #bbbbbb; |
79 |
} |
80 |
</style> |