@v-c/virtual-list 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/Filler.cjs +1 -0
- package/dist/Filler.d.ts +33 -0
- package/dist/Filler.js +57 -0
- package/dist/Item.cjs +1 -0
- package/dist/Item.d.ts +18 -0
- package/dist/Item.js +27 -0
- package/dist/List.cjs +1 -0
- package/dist/List.d.ts +108 -0
- package/dist/List.js +276 -0
- package/dist/ScrollBar.cjs +1 -0
- package/dist/ScrollBar.d.ts +116 -0
- package/dist/ScrollBar.js +193 -0
- package/dist/hooks/useDiffItem.cjs +1 -0
- package/dist/hooks/useDiffItem.d.ts +2 -0
- package/dist/hooks/useDiffItem.js +21 -0
- package/dist/hooks/useFrameWheel.cjs +1 -0
- package/dist/hooks/useFrameWheel.d.ts +11 -0
- package/dist/hooks/useFrameWheel.js +52 -0
- package/dist/hooks/useGetSize.cjs +1 -0
- package/dist/hooks/useGetSize.d.ts +7 -0
- package/dist/hooks/useGetSize.js +24 -0
- package/dist/hooks/useHeights.cjs +1 -0
- package/dist/hooks/useHeights.d.ts +9 -0
- package/dist/hooks/useHeights.js +43 -0
- package/dist/hooks/useMobileTouchMove.cjs +1 -0
- package/dist/hooks/useMobileTouchMove.d.ts +2 -0
- package/dist/hooks/useMobileTouchMove.js +44 -0
- package/dist/hooks/useOriginScroll.cjs +1 -0
- package/dist/hooks/useOriginScroll.d.ts +2 -0
- package/dist/hooks/useOriginScroll.js +17 -0
- package/dist/hooks/useScrollDrag.cjs +1 -0
- package/dist/hooks/useScrollDrag.d.ts +3 -0
- package/dist/hooks/useScrollDrag.js +51 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/interface.cjs +1 -0
- package/dist/interface.d.ts +27 -0
- package/dist/interface.js +1 -0
- package/dist/utils/CacheMap.cjs +1 -0
- package/dist/utils/CacheMap.d.ts +16 -0
- package/dist/utils/CacheMap.js +29 -0
- package/dist/utils/isFirefox.cjs +1 -0
- package/dist/utils/isFirefox.d.ts +2 -0
- package/dist/utils/isFirefox.js +4 -0
- package/dist/utils/scrollbarUtil.cjs +1 -0
- package/dist/utils/scrollbarUtil.d.ts +1 -0
- package/dist/utils/scrollbarUtil.js +7 -0
- package/docs/basic.vue +175 -0
- package/docs/height.vue +48 -0
- package/docs/nest.vue +60 -0
- package/docs/no-virtual.vue +127 -0
- package/docs/switch.vue +101 -0
- package/docs/virtual-list.stories.vue +31 -0
- package/package.json +38 -0
- package/src/Filler.tsx +72 -0
- package/src/Item.tsx +34 -0
- package/src/List.tsx +577 -0
- package/src/ScrollBar.tsx +298 -0
- package/src/__tests__/List.test.ts +59 -0
- package/src/hooks/useDiffItem.ts +27 -0
- package/src/hooks/useFrameWheel.ts +141 -0
- package/src/hooks/useGetSize.ts +44 -0
- package/src/hooks/useHeights.ts +106 -0
- package/src/hooks/useMobileTouchMove.ts +131 -0
- package/src/hooks/useOriginScroll.ts +47 -0
- package/src/hooks/useScrollDrag.ts +123 -0
- package/src/index.ts +5 -0
- package/src/interface.ts +32 -0
- package/src/utils/CacheMap.ts +42 -0
- package/src/utils/isFirefox.ts +3 -0
- package/src/utils/scrollbarUtil.ts +10 -0
- package/vite.config.ts +18 -0
- package/vitest.config.ts +11 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Key } from '../../util/src/type';
|
|
2
|
+
import { CSSProperties, VNode } from 'vue';
|
|
3
|
+
export type RenderFunc<T> = (item: T, index: number, props: {
|
|
4
|
+
style: CSSProperties;
|
|
5
|
+
offsetX: number;
|
|
6
|
+
}) => VNode;
|
|
7
|
+
export interface SharedConfig<T> {
|
|
8
|
+
getKey: (item: T) => Key;
|
|
9
|
+
}
|
|
10
|
+
export type GetKey<T> = (item: T) => Key;
|
|
11
|
+
export type GetSize = (startKey: Key, endKey?: Key) => {
|
|
12
|
+
top: number;
|
|
13
|
+
bottom: number;
|
|
14
|
+
};
|
|
15
|
+
export interface ExtraRenderInfo {
|
|
16
|
+
/** Virtual list start line */
|
|
17
|
+
start: number;
|
|
18
|
+
/** Virtual list end line */
|
|
19
|
+
end: number;
|
|
20
|
+
/** Is current in virtual render */
|
|
21
|
+
virtual: boolean;
|
|
22
|
+
/** Used for `scrollWidth` tell the horizontal offset */
|
|
23
|
+
offsetX: number;
|
|
24
|
+
offsetY: number;
|
|
25
|
+
rtl: boolean;
|
|
26
|
+
getSize: GetSize;
|
|
27
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});class t{maps;id=0;diffRecords=new Map;constructor(){this.maps=Object.create(null)}set(e,s){this.diffRecords.set(e,this.maps[e]),this.maps[e]=s,this.id+=1}get(e){return this.maps[e]}resetRecord(){this.diffRecords.clear()}getRecord(){return this.diffRecords}}exports.default=t;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Key } from '../../../util/src/type';
|
|
2
|
+
declare class CacheMap {
|
|
3
|
+
maps: Record<string, number>;
|
|
4
|
+
id: number;
|
|
5
|
+
diffRecords: Map<Key, number>;
|
|
6
|
+
constructor();
|
|
7
|
+
set(key: Key, value: number): void;
|
|
8
|
+
get(key: Key): number;
|
|
9
|
+
/**
|
|
10
|
+
* CacheMap will record the key changed.
|
|
11
|
+
* To help to know what's update in the next render.
|
|
12
|
+
*/
|
|
13
|
+
resetRecord(): void;
|
|
14
|
+
getRecord(): Map<Key, number>;
|
|
15
|
+
}
|
|
16
|
+
export default CacheMap;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
class r {
|
|
2
|
+
maps;
|
|
3
|
+
// Used for cache key
|
|
4
|
+
// `useMemo` no need to update if `id` not change
|
|
5
|
+
id = 0;
|
|
6
|
+
diffRecords = /* @__PURE__ */ new Map();
|
|
7
|
+
constructor() {
|
|
8
|
+
this.maps = /* @__PURE__ */ Object.create(null);
|
|
9
|
+
}
|
|
10
|
+
set(s, t) {
|
|
11
|
+
this.diffRecords.set(s, this.maps[s]), this.maps[s] = t, this.id += 1;
|
|
12
|
+
}
|
|
13
|
+
get(s) {
|
|
14
|
+
return this.maps[s];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* CacheMap will record the key changed.
|
|
18
|
+
* To help to know what's update in the next render.
|
|
19
|
+
*/
|
|
20
|
+
resetRecord() {
|
|
21
|
+
this.diffRecords.clear();
|
|
22
|
+
}
|
|
23
|
+
getRecord() {
|
|
24
|
+
return this.diffRecords;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
r as default
|
|
29
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=typeof navigator=="object"&&/Firefox/i.test(navigator.userAgent);exports.default=e;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=20;function S(t=0,i=0){let e=t/i*t;return isNaN(e)&&(e=0),e=Math.max(e,o),Math.floor(e)}exports.getSpinSize=S;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getSpinSize(containerSize?: number, scrollRange?: number): number;
|
package/docs/basic.vue
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import VirtualList, { type ListRef } from '../src'
|
|
4
|
+
|
|
5
|
+
interface Item {
|
|
6
|
+
id: number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const data: Item[] = []
|
|
10
|
+
for (let i = 0; i < 1000; i += 1) {
|
|
11
|
+
data.push({ id: i })
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const listRef = ref<ListRef>()
|
|
15
|
+
|
|
16
|
+
function scrollToShowBar() {
|
|
17
|
+
listRef.value?.scrollTo(null)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function scrollTo100px() {
|
|
21
|
+
listRef.value?.scrollTo(500)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function scrollToLarge() {
|
|
25
|
+
listRef.value?.scrollTo({
|
|
26
|
+
index: 99999999,
|
|
27
|
+
align: 'top',
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function scrollTo50Top() {
|
|
32
|
+
listRef.value?.scrollTo({
|
|
33
|
+
index: 50,
|
|
34
|
+
align: 'top',
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function scrollTo50Bottom() {
|
|
39
|
+
listRef.value?.scrollTo({
|
|
40
|
+
index: 50,
|
|
41
|
+
align: 'bottom',
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function scrollTo50Auto() {
|
|
46
|
+
listRef.value?.scrollTo({
|
|
47
|
+
index: 50,
|
|
48
|
+
align: 'auto',
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function scrollTo50TopOffset() {
|
|
53
|
+
listRef.value?.scrollTo({
|
|
54
|
+
index: 50,
|
|
55
|
+
align: 'top',
|
|
56
|
+
offset: 15,
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function scrollTo50BottomOffset() {
|
|
61
|
+
listRef.value?.scrollTo({
|
|
62
|
+
index: 50,
|
|
63
|
+
align: 'bottom',
|
|
64
|
+
offset: 15,
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function scrollToKey50() {
|
|
69
|
+
listRef.value?.scrollTo({
|
|
70
|
+
key: 50,
|
|
71
|
+
align: 'auto',
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function scrollToLast() {
|
|
76
|
+
listRef.value?.scrollTo({
|
|
77
|
+
index: data.length - 2,
|
|
78
|
+
align: 'top',
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function scrollToFirst() {
|
|
83
|
+
listRef.value?.scrollTo({
|
|
84
|
+
index: 0,
|
|
85
|
+
align: 'bottom',
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const visible = ref(true)
|
|
90
|
+
|
|
91
|
+
function onScroll(e: Event) {
|
|
92
|
+
const target = e.currentTarget as HTMLElement
|
|
93
|
+
console.log('scroll:', target.scrollTop)
|
|
94
|
+
}
|
|
95
|
+
</script>
|
|
96
|
+
|
|
97
|
+
<template>
|
|
98
|
+
<div style="height: 200vh">
|
|
99
|
+
<h2>Basic</h2>
|
|
100
|
+
<div style="margin-bottom: 16px">
|
|
101
|
+
<button type="button" style="margin: 4px" @click="scrollToShowBar">
|
|
102
|
+
Show scroll bar
|
|
103
|
+
</button>
|
|
104
|
+
<button type="button" style="margin: 4px" @click="scrollTo100px">
|
|
105
|
+
Scroll To 100px
|
|
106
|
+
</button>
|
|
107
|
+
<button type="button" style="margin: 4px" @click="scrollToLarge">
|
|
108
|
+
Scroll To 99999999 (top)
|
|
109
|
+
</button>
|
|
110
|
+
<button type="button" style="margin: 4px" @click="scrollTo50Top">
|
|
111
|
+
Scroll To 50 (top)
|
|
112
|
+
</button>
|
|
113
|
+
<button type="button" style="margin: 4px" @click="scrollTo50Bottom">
|
|
114
|
+
Scroll To 50 (bottom)
|
|
115
|
+
</button>
|
|
116
|
+
<button type="button" style="margin: 4px" @click="scrollTo50Auto">
|
|
117
|
+
Scroll To 50 (auto)
|
|
118
|
+
</button>
|
|
119
|
+
<br>
|
|
120
|
+
<button type="button" style="margin: 4px" @click="scrollTo50TopOffset">
|
|
121
|
+
Scroll To 50 (top) + 15 offset
|
|
122
|
+
</button>
|
|
123
|
+
<button type="button" style="margin: 4px" @click="scrollTo50BottomOffset">
|
|
124
|
+
Scroll To 50 (bottom) + 15 offset
|
|
125
|
+
</button>
|
|
126
|
+
<button type="button" style="margin: 4px" @click="scrollToKey50">
|
|
127
|
+
Scroll To key 50 (auto)
|
|
128
|
+
</button>
|
|
129
|
+
<button type="button" style="margin: 4px" @click="scrollToLast">
|
|
130
|
+
Scroll To Last (top)
|
|
131
|
+
</button>
|
|
132
|
+
<button type="button" style="margin: 4px" @click="scrollToFirst">
|
|
133
|
+
Scroll To First (bottom)
|
|
134
|
+
</button>
|
|
135
|
+
<button type="button" style="margin: 4px" @click="visible = !visible">
|
|
136
|
+
Toggle visible
|
|
137
|
+
</button>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<VirtualList
|
|
141
|
+
ref="listRef"
|
|
142
|
+
:data="data"
|
|
143
|
+
:height="200"
|
|
144
|
+
:item-height="20"
|
|
145
|
+
item-key="id"
|
|
146
|
+
:style="{
|
|
147
|
+
border: '1px solid red',
|
|
148
|
+
boxSizing: 'border-box',
|
|
149
|
+
display: visible ? '' : 'none',
|
|
150
|
+
}"
|
|
151
|
+
@scroll="onScroll"
|
|
152
|
+
>
|
|
153
|
+
<template #default="{ item }">
|
|
154
|
+
<span
|
|
155
|
+
:style="{
|
|
156
|
+
height: `${30 + (item.id % 2 ? 0 : 10)}px`,
|
|
157
|
+
lineHeight: '30px',
|
|
158
|
+
display: 'inline-block',
|
|
159
|
+
padding: '0 8px',
|
|
160
|
+
}"
|
|
161
|
+
@click="() => console.log('Click:', item.id)"
|
|
162
|
+
>
|
|
163
|
+
{{ item.id }}
|
|
164
|
+
</span>
|
|
165
|
+
</template>
|
|
166
|
+
</VirtualList>
|
|
167
|
+
</div>
|
|
168
|
+
</template>
|
|
169
|
+
|
|
170
|
+
<style scoped>
|
|
171
|
+
button {
|
|
172
|
+
padding: 4px 8px;
|
|
173
|
+
cursor: pointer;
|
|
174
|
+
}
|
|
175
|
+
</style>
|
package/docs/height.vue
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import VirtualList from '../src'
|
|
3
|
+
|
|
4
|
+
interface Item {
|
|
5
|
+
id: number
|
|
6
|
+
height: number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const data: Item[] = []
|
|
10
|
+
for (let i = 0; i < 100; i += 1) {
|
|
11
|
+
data.push({
|
|
12
|
+
id: i,
|
|
13
|
+
height: 30 + (i % 2 ? 70 : 0),
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<div>
|
|
20
|
+
<h2>Dynamic Height</h2>
|
|
21
|
+
|
|
22
|
+
<VirtualList
|
|
23
|
+
:data="data"
|
|
24
|
+
:height="500"
|
|
25
|
+
:item-height="30"
|
|
26
|
+
item-key="id"
|
|
27
|
+
:style="{
|
|
28
|
+
border: '1px solid red',
|
|
29
|
+
boxSizing: 'border-box',
|
|
30
|
+
}"
|
|
31
|
+
>
|
|
32
|
+
<template #default="{ item }">
|
|
33
|
+
<span
|
|
34
|
+
:style="{
|
|
35
|
+
border: '1px solid gray',
|
|
36
|
+
padding: '0 16px',
|
|
37
|
+
height: `${item.height}px`,
|
|
38
|
+
lineHeight: '30px',
|
|
39
|
+
boxSizing: 'border-box',
|
|
40
|
+
display: 'inline-block',
|
|
41
|
+
}"
|
|
42
|
+
>
|
|
43
|
+
{{ item.id }}
|
|
44
|
+
</span>
|
|
45
|
+
</template>
|
|
46
|
+
</VirtualList>
|
|
47
|
+
</div>
|
|
48
|
+
</template>
|
package/docs/nest.vue
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import VirtualList from '../src'
|
|
3
|
+
|
|
4
|
+
interface Item {
|
|
5
|
+
id: number
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const data: Item[] = []
|
|
9
|
+
for (let i = 0; i < 100; i += 1) {
|
|
10
|
+
data.push({ id: i })
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function onScroll(e: Event) {
|
|
14
|
+
// console.log('scroll:', (e.currentTarget as HTMLElement).scrollTop)
|
|
15
|
+
}
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<div>
|
|
20
|
+
<h2>Nested List</h2>
|
|
21
|
+
<VirtualList
|
|
22
|
+
:data="data"
|
|
23
|
+
:height="800"
|
|
24
|
+
:item-height="20"
|
|
25
|
+
item-key="id"
|
|
26
|
+
:style="{
|
|
27
|
+
border: '1px solid red',
|
|
28
|
+
boxSizing: 'border-box',
|
|
29
|
+
}"
|
|
30
|
+
@scroll="onScroll"
|
|
31
|
+
>
|
|
32
|
+
<template #default="{ item }">
|
|
33
|
+
<div :style="{ padding: '20px', background: 'yellow' }">
|
|
34
|
+
<VirtualList
|
|
35
|
+
:data="data"
|
|
36
|
+
:height="200"
|
|
37
|
+
:item-height="20"
|
|
38
|
+
item-key="id"
|
|
39
|
+
:style="{
|
|
40
|
+
border: '1px solid blue',
|
|
41
|
+
boxSizing: 'border-box',
|
|
42
|
+
background: 'white',
|
|
43
|
+
}"
|
|
44
|
+
>
|
|
45
|
+
<template #default="{ item: innerItem, index }">
|
|
46
|
+
<div
|
|
47
|
+
:style="{
|
|
48
|
+
height: '20px',
|
|
49
|
+
border: '1px solid cyan',
|
|
50
|
+
}"
|
|
51
|
+
>
|
|
52
|
+
{{ item.id }}-{{ index }}
|
|
53
|
+
</div>
|
|
54
|
+
</template>
|
|
55
|
+
</VirtualList>
|
|
56
|
+
</div>
|
|
57
|
+
</template>
|
|
58
|
+
</VirtualList>
|
|
59
|
+
</div>
|
|
60
|
+
</template>
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import VirtualList from '../src'
|
|
3
|
+
|
|
4
|
+
interface Item {
|
|
5
|
+
id: number
|
|
6
|
+
height: number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const data: Item[] = []
|
|
10
|
+
for (let i = 0; i < 100; i += 1) {
|
|
11
|
+
data.push({
|
|
12
|
+
id: i,
|
|
13
|
+
height: 30 + (i % 2 ? 20 : 0),
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<div>
|
|
20
|
+
<h2>Not Data</h2>
|
|
21
|
+
<VirtualList
|
|
22
|
+
:data="null"
|
|
23
|
+
:item-height="30"
|
|
24
|
+
:height="100"
|
|
25
|
+
item-key="id"
|
|
26
|
+
:style="{
|
|
27
|
+
border: '1px solid red',
|
|
28
|
+
boxSizing: 'border-box',
|
|
29
|
+
}"
|
|
30
|
+
>
|
|
31
|
+
<template #default="{ item }">
|
|
32
|
+
<span
|
|
33
|
+
:style="{
|
|
34
|
+
border: '1px solid gray',
|
|
35
|
+
padding: '0 16px',
|
|
36
|
+
height: `${item.height}px`,
|
|
37
|
+
lineHeight: '30px',
|
|
38
|
+
boxSizing: 'border-box',
|
|
39
|
+
display: 'inline-block',
|
|
40
|
+
}"
|
|
41
|
+
>
|
|
42
|
+
{{ item.id }}
|
|
43
|
+
</span>
|
|
44
|
+
</template>
|
|
45
|
+
</VirtualList>
|
|
46
|
+
|
|
47
|
+
<h2>Less Count</h2>
|
|
48
|
+
<VirtualList
|
|
49
|
+
:data="data.slice(0, 1)"
|
|
50
|
+
:item-height="30"
|
|
51
|
+
:height="100"
|
|
52
|
+
item-key="id"
|
|
53
|
+
:style="{
|
|
54
|
+
border: '1px solid red',
|
|
55
|
+
boxSizing: 'border-box',
|
|
56
|
+
}"
|
|
57
|
+
>
|
|
58
|
+
<template #default="{ item }">
|
|
59
|
+
<span
|
|
60
|
+
:style="{
|
|
61
|
+
border: '1px solid gray',
|
|
62
|
+
padding: '0 16px',
|
|
63
|
+
height: `${item.height}px`,
|
|
64
|
+
lineHeight: '30px',
|
|
65
|
+
boxSizing: 'border-box',
|
|
66
|
+
display: 'inline-block',
|
|
67
|
+
}"
|
|
68
|
+
>
|
|
69
|
+
{{ item.id }}
|
|
70
|
+
</span>
|
|
71
|
+
</template>
|
|
72
|
+
</VirtualList>
|
|
73
|
+
|
|
74
|
+
<h2>Less Item Height</h2>
|
|
75
|
+
<VirtualList
|
|
76
|
+
:data="data.slice(0, 10)"
|
|
77
|
+
:item-height="1"
|
|
78
|
+
:height="100"
|
|
79
|
+
item-key="id"
|
|
80
|
+
:style="{
|
|
81
|
+
border: '1px solid red',
|
|
82
|
+
boxSizing: 'border-box',
|
|
83
|
+
}"
|
|
84
|
+
>
|
|
85
|
+
<template #default="{ item }">
|
|
86
|
+
<span
|
|
87
|
+
:style="{
|
|
88
|
+
border: '1px solid gray',
|
|
89
|
+
padding: '0 16px',
|
|
90
|
+
height: `${item.height}px`,
|
|
91
|
+
lineHeight: '30px',
|
|
92
|
+
boxSizing: 'border-box',
|
|
93
|
+
display: 'inline-block',
|
|
94
|
+
}"
|
|
95
|
+
>
|
|
96
|
+
{{ item.id }}
|
|
97
|
+
</span>
|
|
98
|
+
</template>
|
|
99
|
+
</VirtualList>
|
|
100
|
+
|
|
101
|
+
<h2>Without Height</h2>
|
|
102
|
+
<VirtualList
|
|
103
|
+
:data="data"
|
|
104
|
+
:item-height="30"
|
|
105
|
+
item-key="id"
|
|
106
|
+
:style="{
|
|
107
|
+
border: '1px solid red',
|
|
108
|
+
boxSizing: 'border-box',
|
|
109
|
+
}"
|
|
110
|
+
>
|
|
111
|
+
<template #default="{ item }">
|
|
112
|
+
<span
|
|
113
|
+
:style="{
|
|
114
|
+
border: '1px solid gray',
|
|
115
|
+
padding: '0 16px',
|
|
116
|
+
height: `${item.height}px`,
|
|
117
|
+
lineHeight: '30px',
|
|
118
|
+
boxSizing: 'border-box',
|
|
119
|
+
display: 'inline-block',
|
|
120
|
+
}"
|
|
121
|
+
>
|
|
122
|
+
{{ item.id }}
|
|
123
|
+
</span>
|
|
124
|
+
</template>
|
|
125
|
+
</VirtualList>
|
|
126
|
+
</div>
|
|
127
|
+
</template>
|
package/docs/switch.vue
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import VirtualList, { type ListRef } from '../src'
|
|
4
|
+
|
|
5
|
+
interface Item {
|
|
6
|
+
id: number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function getData(count: number): Item[] {
|
|
10
|
+
const result: Item[] = []
|
|
11
|
+
for (let i = 0; i < count; i += 1) {
|
|
12
|
+
result.push({ id: i })
|
|
13
|
+
}
|
|
14
|
+
return result
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const height = ref(200)
|
|
18
|
+
const data = ref(getData(20))
|
|
19
|
+
const fullHeight = ref(true)
|
|
20
|
+
const listRef = ref<ListRef>()
|
|
21
|
+
|
|
22
|
+
function setDataCount(count: number) {
|
|
23
|
+
data.value = getData(count)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function showScrollbar() {
|
|
27
|
+
listRef.value?.scrollTo(null)
|
|
28
|
+
}
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<div style="height: 150vh">
|
|
33
|
+
<h2>Switch</h2>
|
|
34
|
+
<div style="margin-bottom: 16px">
|
|
35
|
+
<span>
|
|
36
|
+
Data:
|
|
37
|
+
<label><input type="radio" name="data" value="0" @change="() => setDataCount(0)"> 0</label>
|
|
38
|
+
<label><input type="radio" name="data" value="2" @change="() => setDataCount(2)"> 2</label>
|
|
39
|
+
<label><input type="radio" name="data" value="20" checked @change="() => setDataCount(20)"> 20</label>
|
|
40
|
+
<label><input type="radio" name="data" value="100" @change="() => setDataCount(100)"> 100</label>
|
|
41
|
+
<label><input type="radio" name="data" value="200" @change="() => setDataCount(200)"> 200</label>
|
|
42
|
+
<label><input type="radio" name="data" value="1000" @change="() => setDataCount(1000)"> 1000</label>
|
|
43
|
+
<button type="button" @click="showScrollbar">
|
|
44
|
+
Show scrollbar
|
|
45
|
+
</button>
|
|
46
|
+
</span>
|
|
47
|
+
<br>
|
|
48
|
+
<span>
|
|
49
|
+
Height:
|
|
50
|
+
<label><input type="radio" name="height" value="0" @change="() => height = 0"> 0</label>
|
|
51
|
+
<label><input type="radio" name="height" value="100" @change="() => height = 100"> 100</label>
|
|
52
|
+
<label><input type="radio" name="height" value="200" checked @change="() => height = 200"> 200</label>
|
|
53
|
+
</span>
|
|
54
|
+
<span style="margin-left: 16px">
|
|
55
|
+
<button @click="fullHeight = !fullHeight">
|
|
56
|
+
Full Height: {{ fullHeight }}
|
|
57
|
+
</button>
|
|
58
|
+
</span>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<VirtualList
|
|
62
|
+
ref="listRef"
|
|
63
|
+
:data="data"
|
|
64
|
+
:height="height"
|
|
65
|
+
:item-height="10"
|
|
66
|
+
item-key="id"
|
|
67
|
+
:full-height="fullHeight"
|
|
68
|
+
:style="{
|
|
69
|
+
border: '1px solid red',
|
|
70
|
+
boxSizing: 'border-box',
|
|
71
|
+
}"
|
|
72
|
+
>
|
|
73
|
+
<template #default="{ item }">
|
|
74
|
+
<span
|
|
75
|
+
:style="{
|
|
76
|
+
border: '1px solid gray',
|
|
77
|
+
padding: '0 16px',
|
|
78
|
+
height: '30px',
|
|
79
|
+
lineHeight: '30px',
|
|
80
|
+
boxSizing: 'border-box',
|
|
81
|
+
display: 'inline-block',
|
|
82
|
+
}"
|
|
83
|
+
>
|
|
84
|
+
{{ item.id }}
|
|
85
|
+
</span>
|
|
86
|
+
</template>
|
|
87
|
+
</VirtualList>
|
|
88
|
+
</div>
|
|
89
|
+
</template>
|
|
90
|
+
|
|
91
|
+
<style scoped>
|
|
92
|
+
label {
|
|
93
|
+
margin-left: 8px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
button {
|
|
97
|
+
margin-left: 8px;
|
|
98
|
+
padding: 4px 8px;
|
|
99
|
+
cursor: pointer;
|
|
100
|
+
}
|
|
101
|
+
</style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import Basic from './basic.vue'
|
|
3
|
+
import Height from './height.vue'
|
|
4
|
+
import Nest from './nest.vue'
|
|
5
|
+
import NoVirtual from './no-virtual.vue'
|
|
6
|
+
import Switch from './switch.vue'
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<Story title="Virtual List">
|
|
11
|
+
<Variant title="Basic">
|
|
12
|
+
<Basic />
|
|
13
|
+
</Variant>
|
|
14
|
+
|
|
15
|
+
<Variant title="Dynamic Height">
|
|
16
|
+
<Height />
|
|
17
|
+
</Variant>
|
|
18
|
+
|
|
19
|
+
<Variant title="No Virtual">
|
|
20
|
+
<NoVirtual />
|
|
21
|
+
</Variant>
|
|
22
|
+
|
|
23
|
+
<Variant title="Switch Data">
|
|
24
|
+
<Switch />
|
|
25
|
+
</Variant>
|
|
26
|
+
|
|
27
|
+
<Variant title="Nested">
|
|
28
|
+
<Nest />
|
|
29
|
+
</Variant>
|
|
30
|
+
</Story>
|
|
31
|
+
</template>
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@v-c/virtual-list",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"import": "./dist/index.js",
|
|
9
|
+
"require": "./dist/index.cjs"
|
|
10
|
+
},
|
|
11
|
+
"./dist/*": "./dist/*",
|
|
12
|
+
"./package.json": "./package.json"
|
|
13
|
+
},
|
|
14
|
+
"description": "Vue Virtual List Component",
|
|
15
|
+
"author": "",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"keywords": [
|
|
18
|
+
"vue",
|
|
19
|
+
"virtual-list",
|
|
20
|
+
"vue-component"
|
|
21
|
+
],
|
|
22
|
+
"main": "index.js",
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"vue": "^3.0.0"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@v-c/resize-observer": "0.0.2",
|
|
31
|
+
"@v-c/util": "0.0.7"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "vite build",
|
|
35
|
+
"test": "vitest",
|
|
36
|
+
"prepublish": "pnpm build"
|
|
37
|
+
}
|
|
38
|
+
}
|