@v-c/virtual-list 1.0.0 → 1.0.2
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/dist/List.cjs +18 -9
- package/dist/List.js +19 -10
- package/dist/hooks/useHeights.cjs +1 -1
- package/dist/hooks/useHeights.js +2 -2
- package/package.json +6 -2
- package/bump.config.ts +0 -6
- package/docs/animate.less +0 -31
- package/docs/animate.vue +0 -159
- package/docs/basic.vue +0 -176
- package/docs/height.vue +0 -48
- package/docs/nest.vue +0 -60
- package/docs/no-virtual.vue +0 -127
- package/docs/switch.vue +0 -102
- package/docs/virtual-list.stories.vue +0 -35
- package/src/Filler.tsx +0 -73
- package/src/Item.tsx +0 -35
- package/src/List.tsx +0 -642
- package/src/ScrollBar.tsx +0 -287
- package/src/__tests__/List.test.ts +0 -59
- package/src/hooks/useDiffItem.ts +0 -28
- package/src/hooks/useFrameWheel.ts +0 -142
- package/src/hooks/useGetSize.ts +0 -45
- package/src/hooks/useHeights.ts +0 -107
- package/src/hooks/useMobileTouchMove.ts +0 -132
- package/src/hooks/useOriginScroll.ts +0 -48
- package/src/hooks/useScrollDrag.ts +0 -124
- package/src/hooks/useScrollTo.tsx +0 -184
- package/src/index.ts +0 -5
- package/src/interface.ts +0 -32
- package/src/utils/CacheMap.ts +0 -42
- package/src/utils/isFirefox.ts +0 -3
- package/src/utils/scrollbarUtil.ts +0 -10
- package/tsconfig.json +0 -7
- package/vite.config.ts +0 -18
- package/vitest.config.ts +0 -11
package/dist/List.cjs
CHANGED
|
@@ -2,7 +2,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
2
2
|
const require_rolldown_runtime = require("./_virtual/rolldown_runtime.cjs");
|
|
3
3
|
const require_Filler = require("./Filler.cjs");
|
|
4
4
|
const require_Item = require("./Item.cjs");
|
|
5
|
-
const require_useDiffItem = require("./hooks/useDiffItem.cjs");
|
|
6
5
|
const require_useFrameWheel = require("./hooks/useFrameWheel.cjs");
|
|
7
6
|
const require_useGetSize = require("./hooks/useGetSize.cjs");
|
|
8
7
|
const require_useHeights = require("./hooks/useHeights.cjs");
|
|
@@ -69,12 +68,18 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
69
68
|
inheritAttrs: false,
|
|
70
69
|
setup(props, { expose, attrs, slots }) {
|
|
71
70
|
const itemHeight = (0, vue.computed)(() => props.itemHeight);
|
|
71
|
+
const itemKey = (0, vue.toRef)(props, "itemKey");
|
|
72
72
|
const getKey = (item) => {
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
item = (0, vue.toRaw)(item);
|
|
74
|
+
const _itemKey = itemKey.value;
|
|
75
|
+
if (typeof _itemKey === "function") return _itemKey(item);
|
|
76
|
+
return item?.[_itemKey];
|
|
75
77
|
};
|
|
76
78
|
const [setInstanceRef, collectHeight, heights, heightUpdatedMark] = require_useHeights.default(getKey, void 0, void 0);
|
|
77
|
-
const mergedData = (0, vue.
|
|
79
|
+
const mergedData = (0, vue.shallowRef)(props?.data || EMPTY_DATA);
|
|
80
|
+
(0, vue.watch)(() => props.data, () => {
|
|
81
|
+
mergedData.value = props?.data || EMPTY_DATA;
|
|
82
|
+
});
|
|
78
83
|
const useVirtual = (0, vue.computed)(() => !!(props.virtual !== false && props.height && props.itemHeight));
|
|
79
84
|
const containerHeight = (0, vue.computed)(() => Object.values(heights.maps).reduce((total, curr) => total + curr, 0));
|
|
80
85
|
const inVirtual = (0, vue.computed)(() => {
|
|
@@ -105,7 +110,6 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
105
110
|
if (componentRef.value) componentRef.value.scrollTop = alignedTop;
|
|
106
111
|
offsetTop.value = alignedTop;
|
|
107
112
|
}
|
|
108
|
-
require_useDiffItem.default(mergedData, getKey);
|
|
109
113
|
(0, vue.watch)([
|
|
110
114
|
inVirtual,
|
|
111
115
|
useVirtual,
|
|
@@ -121,6 +125,7 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
121
125
|
fillerOffset.value = void 0;
|
|
122
126
|
return;
|
|
123
127
|
}
|
|
128
|
+
const { itemHeight: itemHeight$1, height } = props;
|
|
124
129
|
if (!inVirtual.value) {
|
|
125
130
|
scrollHeight.value = fillerInnerRef.value?.offsetHeight || 0;
|
|
126
131
|
start.value = 0;
|
|
@@ -133,23 +138,27 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
133
138
|
let startOffset;
|
|
134
139
|
let endIndex;
|
|
135
140
|
const dataLen = mergedData.value.length;
|
|
136
|
-
const data = mergedData.value;
|
|
141
|
+
const data = (0, vue.toRaw)(mergedData.value);
|
|
137
142
|
for (let i = 0; i < dataLen; i += 1) {
|
|
138
143
|
const item = data[i];
|
|
139
144
|
const key = getKey(item);
|
|
140
145
|
const cacheHeight = heights.get(key);
|
|
141
|
-
const currentItemBottom = itemTop + (cacheHeight === void 0 ?
|
|
146
|
+
const currentItemBottom = itemTop + (cacheHeight === void 0 ? itemHeight$1 : cacheHeight);
|
|
142
147
|
if (currentItemBottom >= offsetTop.value && startIndex === void 0) {
|
|
143
148
|
startIndex = i;
|
|
144
149
|
startOffset = itemTop;
|
|
145
150
|
}
|
|
146
|
-
if (currentItemBottom > offsetTop.value +
|
|
151
|
+
if (currentItemBottom > offsetTop.value + height && endIndex === void 0) endIndex = i;
|
|
147
152
|
itemTop = currentItemBottom;
|
|
153
|
+
if (startIndex !== void 0 && endIndex !== void 0) {
|
|
154
|
+
itemTop = currentItemBottom + (dataLen - 1 - i) * itemHeight$1;
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
148
157
|
}
|
|
149
158
|
if (startIndex === void 0) {
|
|
150
159
|
startIndex = 0;
|
|
151
160
|
startOffset = 0;
|
|
152
|
-
endIndex = Math.ceil(
|
|
161
|
+
endIndex = Math.ceil(height / itemHeight$1);
|
|
153
162
|
}
|
|
154
163
|
if (endIndex === void 0) endIndex = mergedData.value.length - 1;
|
|
155
164
|
endIndex = Math.min(endIndex + 1, mergedData.value.length - 1);
|
package/dist/List.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import Filler_default from "./Filler.js";
|
|
2
2
|
import Item_default from "./Item.js";
|
|
3
|
-
import useDiffItem from "./hooks/useDiffItem.js";
|
|
4
3
|
import useFrameWheel from "./hooks/useFrameWheel.js";
|
|
5
4
|
import { useGetSize } from "./hooks/useGetSize.js";
|
|
6
5
|
import useHeights from "./hooks/useHeights.js";
|
|
@@ -9,7 +8,7 @@ import useScrollDrag from "./hooks/useScrollDrag.js";
|
|
|
9
8
|
import useScrollTo from "./hooks/useScrollTo.js";
|
|
10
9
|
import ScrollBar_default from "./ScrollBar.js";
|
|
11
10
|
import { getSpinSize } from "./utils/scrollbarUtil.js";
|
|
12
|
-
import { computed, createVNode, defineComponent, isVNode, mergeProps, ref, shallowRef, watch } from "vue";
|
|
11
|
+
import { computed, createVNode, defineComponent, isVNode, mergeProps, ref, shallowRef, toRaw, toRef, watch } from "vue";
|
|
13
12
|
import ResizeObserver from "@v-c/resize-observer";
|
|
14
13
|
import { pureAttrs } from "@v-c/util/dist/props-util";
|
|
15
14
|
function _isSlot(s) {
|
|
@@ -66,12 +65,18 @@ var List_default = /* @__PURE__ */ defineComponent({
|
|
|
66
65
|
inheritAttrs: false,
|
|
67
66
|
setup(props, { expose, attrs, slots }) {
|
|
68
67
|
const itemHeight = computed(() => props.itemHeight);
|
|
68
|
+
const itemKey = toRef(props, "itemKey");
|
|
69
69
|
const getKey = (item) => {
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
item = toRaw(item);
|
|
71
|
+
const _itemKey = itemKey.value;
|
|
72
|
+
if (typeof _itemKey === "function") return _itemKey(item);
|
|
73
|
+
return item?.[_itemKey];
|
|
72
74
|
};
|
|
73
75
|
const [setInstanceRef, collectHeight, heights, heightUpdatedMark] = useHeights(getKey, void 0, void 0);
|
|
74
|
-
const mergedData =
|
|
76
|
+
const mergedData = shallowRef(props?.data || EMPTY_DATA);
|
|
77
|
+
watch(() => props.data, () => {
|
|
78
|
+
mergedData.value = props?.data || EMPTY_DATA;
|
|
79
|
+
});
|
|
75
80
|
const useVirtual = computed(() => !!(props.virtual !== false && props.height && props.itemHeight));
|
|
76
81
|
const containerHeight = computed(() => Object.values(heights.maps).reduce((total, curr) => total + curr, 0));
|
|
77
82
|
const inVirtual = computed(() => {
|
|
@@ -102,7 +107,6 @@ var List_default = /* @__PURE__ */ defineComponent({
|
|
|
102
107
|
if (componentRef.value) componentRef.value.scrollTop = alignedTop;
|
|
103
108
|
offsetTop.value = alignedTop;
|
|
104
109
|
}
|
|
105
|
-
useDiffItem(mergedData, getKey);
|
|
106
110
|
watch([
|
|
107
111
|
inVirtual,
|
|
108
112
|
useVirtual,
|
|
@@ -118,6 +122,7 @@ var List_default = /* @__PURE__ */ defineComponent({
|
|
|
118
122
|
fillerOffset.value = void 0;
|
|
119
123
|
return;
|
|
120
124
|
}
|
|
125
|
+
const { itemHeight: itemHeight$1, height } = props;
|
|
121
126
|
if (!inVirtual.value) {
|
|
122
127
|
scrollHeight.value = fillerInnerRef.value?.offsetHeight || 0;
|
|
123
128
|
start.value = 0;
|
|
@@ -130,23 +135,27 @@ var List_default = /* @__PURE__ */ defineComponent({
|
|
|
130
135
|
let startOffset;
|
|
131
136
|
let endIndex;
|
|
132
137
|
const dataLen = mergedData.value.length;
|
|
133
|
-
const data = mergedData.value;
|
|
138
|
+
const data = toRaw(mergedData.value);
|
|
134
139
|
for (let i = 0; i < dataLen; i += 1) {
|
|
135
140
|
const item = data[i];
|
|
136
141
|
const key = getKey(item);
|
|
137
142
|
const cacheHeight = heights.get(key);
|
|
138
|
-
const currentItemBottom = itemTop + (cacheHeight === void 0 ?
|
|
143
|
+
const currentItemBottom = itemTop + (cacheHeight === void 0 ? itemHeight$1 : cacheHeight);
|
|
139
144
|
if (currentItemBottom >= offsetTop.value && startIndex === void 0) {
|
|
140
145
|
startIndex = i;
|
|
141
146
|
startOffset = itemTop;
|
|
142
147
|
}
|
|
143
|
-
if (currentItemBottom > offsetTop.value +
|
|
148
|
+
if (currentItemBottom > offsetTop.value + height && endIndex === void 0) endIndex = i;
|
|
144
149
|
itemTop = currentItemBottom;
|
|
150
|
+
if (startIndex !== void 0 && endIndex !== void 0) {
|
|
151
|
+
itemTop = currentItemBottom + (dataLen - 1 - i) * itemHeight$1;
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
145
154
|
}
|
|
146
155
|
if (startIndex === void 0) {
|
|
147
156
|
startIndex = 0;
|
|
148
157
|
startOffset = 0;
|
|
149
|
-
endIndex = Math.ceil(
|
|
158
|
+
endIndex = Math.ceil(height / itemHeight$1);
|
|
150
159
|
}
|
|
151
160
|
if (endIndex === void 0) endIndex = mergedData.value.length - 1;
|
|
152
161
|
endIndex = Math.min(endIndex + 1, mergedData.value.length - 1);
|
|
@@ -9,7 +9,7 @@ function parseNumber(value) {
|
|
|
9
9
|
function useHeights(getKey, onItemAdd, onItemRemove) {
|
|
10
10
|
const updatedMark = (0, vue.ref)(0);
|
|
11
11
|
const instanceRef = (0, vue.ref)(/* @__PURE__ */ new Map());
|
|
12
|
-
const heightsRef =
|
|
12
|
+
const heightsRef = new require_CacheMap.default();
|
|
13
13
|
const promiseIdRef = (0, vue.ref)(0);
|
|
14
14
|
function cancelRaf() {
|
|
15
15
|
promiseIdRef.value += 1;
|
package/dist/hooks/useHeights.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import CacheMap_default from "../utils/CacheMap.js";
|
|
2
|
-
import { onUnmounted,
|
|
2
|
+
import { onUnmounted, ref } from "vue";
|
|
3
3
|
function parseNumber(value) {
|
|
4
4
|
const num = parseFloat(value);
|
|
5
5
|
return isNaN(num) ? 0 : num;
|
|
@@ -7,7 +7,7 @@ function parseNumber(value) {
|
|
|
7
7
|
function useHeights(getKey, onItemAdd, onItemRemove) {
|
|
8
8
|
const updatedMark = ref(0);
|
|
9
9
|
const instanceRef = ref(/* @__PURE__ */ new Map());
|
|
10
|
-
const heightsRef =
|
|
10
|
+
const heightsRef = new CacheMap_default();
|
|
11
11
|
const promiseIdRef = ref(0);
|
|
12
12
|
function cancelRaf() {
|
|
13
13
|
promiseIdRef.value += 1;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@v-c/virtual-list",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.2",
|
|
5
5
|
"description": "Vue Virtual List Component",
|
|
6
6
|
"author": "",
|
|
7
7
|
"license": "MIT",
|
|
@@ -20,6 +20,10 @@
|
|
|
20
20
|
"./package.json": "./package.json"
|
|
21
21
|
},
|
|
22
22
|
"main": "./dist/index.js",
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"package.json"
|
|
26
|
+
],
|
|
23
27
|
"publishConfig": {
|
|
24
28
|
"access": "public"
|
|
25
29
|
},
|
|
@@ -28,7 +32,7 @@
|
|
|
28
32
|
},
|
|
29
33
|
"dependencies": {
|
|
30
34
|
"@v-c/resize-observer": "^1.0.0",
|
|
31
|
-
"@v-c/util": "^1.0.
|
|
35
|
+
"@v-c/util": "^1.0.2"
|
|
32
36
|
},
|
|
33
37
|
"scripts": {
|
|
34
38
|
"build": "vite build",
|
package/bump.config.ts
DELETED
package/docs/animate.less
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
.motion {
|
|
2
|
-
transition: all 0.3s;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
.item {
|
|
6
|
-
display: inline-block;
|
|
7
|
-
box-sizing: border-box;
|
|
8
|
-
margin: 0;
|
|
9
|
-
padding: 0 16px;
|
|
10
|
-
overflow: hidden;
|
|
11
|
-
line-height: 31px;
|
|
12
|
-
position: relative;
|
|
13
|
-
|
|
14
|
-
&:hover {
|
|
15
|
-
background: rgba(255, 0, 0, 0.1);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
&::after {
|
|
19
|
-
content: '';
|
|
20
|
-
border-bottom: 1px solid gray;
|
|
21
|
-
position: absolute;
|
|
22
|
-
bottom: 0;
|
|
23
|
-
left: 0;
|
|
24
|
-
right: 0;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
button {
|
|
28
|
-
vertical-align: text-top;
|
|
29
|
-
margin-right: 8px;
|
|
30
|
-
}
|
|
31
|
-
}
|
package/docs/animate.vue
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { ListRef } from '../src'
|
|
3
|
-
import { ref } from 'vue'
|
|
4
|
-
import VirtualList from '../src'
|
|
5
|
-
import './animate.less'
|
|
6
|
-
|
|
7
|
-
interface Item {
|
|
8
|
-
id: string
|
|
9
|
-
uuid: number
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
let uuid = 0
|
|
13
|
-
function genItem(): Item {
|
|
14
|
-
const item = {
|
|
15
|
-
id: `key_${uuid}`,
|
|
16
|
-
uuid,
|
|
17
|
-
}
|
|
18
|
-
uuid += 1
|
|
19
|
-
return item
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const originData: Item[] = []
|
|
23
|
-
for (let i = 0; i < 1000; i += 1) {
|
|
24
|
-
originData.push(genItem())
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const data = ref([...originData])
|
|
28
|
-
const closeMap = ref<Record<string, boolean>>({})
|
|
29
|
-
const animating = ref(false)
|
|
30
|
-
const insertIndex = ref<number>()
|
|
31
|
-
|
|
32
|
-
const listRef = ref<ListRef>()
|
|
33
|
-
|
|
34
|
-
function onClose(id: string) {
|
|
35
|
-
closeMap.value = {
|
|
36
|
-
...closeMap.value,
|
|
37
|
-
[id]: true,
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function onLeave(id: string) {
|
|
42
|
-
data.value = data.value.filter(item => item.id !== id)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function onAppear(...args: any[]) {
|
|
46
|
-
console.log('Appear:', args)
|
|
47
|
-
animating.value = false
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function lockForAnimation() {
|
|
51
|
-
animating.value = true
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function onInsertBefore(id: string) {
|
|
55
|
-
const index = data.value.findIndex(item => item.id === id)
|
|
56
|
-
const newData = [...data.value.slice(0, index), genItem(), ...data.value.slice(index)]
|
|
57
|
-
insertIndex.value = index
|
|
58
|
-
data.value = newData
|
|
59
|
-
lockForAnimation()
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function onInsertAfter(id: string) {
|
|
63
|
-
const index = data.value.findIndex(item => item.id === id) + 1
|
|
64
|
-
const newData = [...data.value.slice(0, index), genItem(), ...data.value.slice(index)]
|
|
65
|
-
insertIndex.value = index
|
|
66
|
-
data.value = newData
|
|
67
|
-
lockForAnimation()
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function getCurrentHeight(el: Element) {
|
|
71
|
-
const node = el as HTMLElement
|
|
72
|
-
node.style.height = `${node.offsetHeight}px`
|
|
73
|
-
node.style.opacity = '1'
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function getMaxHeight(el: Element) {
|
|
77
|
-
const node = el as HTMLElement
|
|
78
|
-
node.style.height = `${node.scrollHeight}px`
|
|
79
|
-
node.style.opacity = '1'
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function getCollapsedHeight(el: Element) {
|
|
83
|
-
const node = el as HTMLElement
|
|
84
|
-
node.style.height = '0'
|
|
85
|
-
node.style.opacity = '0'
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function resetHeight(el: Element) {
|
|
89
|
-
const node = el as HTMLElement
|
|
90
|
-
node.style.height = ''
|
|
91
|
-
node.style.opacity = ''
|
|
92
|
-
onAppear()
|
|
93
|
-
}
|
|
94
|
-
</script>
|
|
95
|
-
|
|
96
|
-
<template>
|
|
97
|
-
<div>
|
|
98
|
-
<h2>Animate</h2>
|
|
99
|
-
<p>Current: {{ data.length }} records</p>
|
|
100
|
-
|
|
101
|
-
<VirtualList
|
|
102
|
-
ref="listRef"
|
|
103
|
-
:data="data"
|
|
104
|
-
data-id="list"
|
|
105
|
-
:height="200"
|
|
106
|
-
:item-height="20"
|
|
107
|
-
item-key="id"
|
|
108
|
-
:style="{
|
|
109
|
-
border: '1px solid red',
|
|
110
|
-
boxSizing: 'border-box',
|
|
111
|
-
}"
|
|
112
|
-
>
|
|
113
|
-
<template #default="{ item, index }">
|
|
114
|
-
<Transition
|
|
115
|
-
name="motion"
|
|
116
|
-
:appear="animating && insertIndex === index"
|
|
117
|
-
@before-enter="getCollapsedHeight"
|
|
118
|
-
@enter="getMaxHeight"
|
|
119
|
-
@after-enter="resetHeight"
|
|
120
|
-
@before-leave="getCurrentHeight"
|
|
121
|
-
@leave="getCollapsedHeight"
|
|
122
|
-
@after-leave="() => onLeave(item.id)"
|
|
123
|
-
>
|
|
124
|
-
<div
|
|
125
|
-
v-if="!(closeMap as any)[item.id]"
|
|
126
|
-
class="item"
|
|
127
|
-
:data-id="item.id"
|
|
128
|
-
>
|
|
129
|
-
<div :style="{ height: item.uuid % 2 ? '100px' : undefined }">
|
|
130
|
-
<button type="button" @click="onClose(item.id)">
|
|
131
|
-
Close
|
|
132
|
-
</button>
|
|
133
|
-
<button type="button" @click="onInsertBefore(item.id)">
|
|
134
|
-
Insert Before
|
|
135
|
-
</button>
|
|
136
|
-
<button type="button" @click="onInsertAfter(item.id)">
|
|
137
|
-
Insert After
|
|
138
|
-
</button>
|
|
139
|
-
{{ item.id }}
|
|
140
|
-
</div>
|
|
141
|
-
</div>
|
|
142
|
-
</Transition>
|
|
143
|
-
</template>
|
|
144
|
-
</VirtualList>
|
|
145
|
-
</div>
|
|
146
|
-
</template>
|
|
147
|
-
|
|
148
|
-
<style scoped>
|
|
149
|
-
.motion-enter-active,
|
|
150
|
-
.motion-leave-active {
|
|
151
|
-
transition: all 0.3s;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
.motion-enter-from,
|
|
155
|
-
.motion-leave-to {
|
|
156
|
-
height: 0;
|
|
157
|
-
opacity: 0;
|
|
158
|
-
}
|
|
159
|
-
</style>
|
package/docs/basic.vue
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { ListRef } from '../src'
|
|
3
|
-
import { ref } from 'vue'
|
|
4
|
-
import VirtualList from '../src'
|
|
5
|
-
|
|
6
|
-
interface Item {
|
|
7
|
-
id: number
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const data: Item[] = []
|
|
11
|
-
for (let i = 0; i < 1000; i += 1) {
|
|
12
|
-
data.push({ id: i })
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const listRef = ref<ListRef>()
|
|
16
|
-
|
|
17
|
-
function scrollToShowBar() {
|
|
18
|
-
listRef.value?.scrollTo(null)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function scrollTo100px() {
|
|
22
|
-
listRef.value?.scrollTo(500)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function scrollToLarge() {
|
|
26
|
-
listRef.value?.scrollTo({
|
|
27
|
-
index: 99999999,
|
|
28
|
-
align: 'top',
|
|
29
|
-
})
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function scrollTo50Top() {
|
|
33
|
-
listRef.value?.scrollTo({
|
|
34
|
-
index: 50,
|
|
35
|
-
align: 'top',
|
|
36
|
-
})
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function scrollTo50Bottom() {
|
|
40
|
-
listRef.value?.scrollTo({
|
|
41
|
-
index: 50,
|
|
42
|
-
align: 'bottom',
|
|
43
|
-
})
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function scrollTo50Auto() {
|
|
47
|
-
listRef.value?.scrollTo({
|
|
48
|
-
index: 50,
|
|
49
|
-
align: 'auto',
|
|
50
|
-
})
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function scrollTo50TopOffset() {
|
|
54
|
-
listRef.value?.scrollTo({
|
|
55
|
-
index: 50,
|
|
56
|
-
align: 'top',
|
|
57
|
-
offset: 15,
|
|
58
|
-
})
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function scrollTo50BottomOffset() {
|
|
62
|
-
listRef.value?.scrollTo({
|
|
63
|
-
index: 50,
|
|
64
|
-
align: 'bottom',
|
|
65
|
-
offset: 15,
|
|
66
|
-
})
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function scrollToKey50() {
|
|
70
|
-
listRef.value?.scrollTo({
|
|
71
|
-
key: 50,
|
|
72
|
-
align: 'auto',
|
|
73
|
-
})
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function scrollToLast() {
|
|
77
|
-
listRef.value?.scrollTo({
|
|
78
|
-
index: data.length - 2,
|
|
79
|
-
align: 'top',
|
|
80
|
-
})
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function scrollToFirst() {
|
|
84
|
-
listRef.value?.scrollTo({
|
|
85
|
-
index: 0,
|
|
86
|
-
align: 'bottom',
|
|
87
|
-
})
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const visible = ref(true)
|
|
91
|
-
|
|
92
|
-
function onScroll(e: Event) {
|
|
93
|
-
const target = e.currentTarget as HTMLElement
|
|
94
|
-
console.log('scroll:', target.scrollTop)
|
|
95
|
-
}
|
|
96
|
-
</script>
|
|
97
|
-
|
|
98
|
-
<template>
|
|
99
|
-
<div style="height: 200vh">
|
|
100
|
-
<h2>Basic</h2>
|
|
101
|
-
<div style="margin-bottom: 16px">
|
|
102
|
-
<button type="button" style="margin: 4px" @click="scrollToShowBar">
|
|
103
|
-
Show scroll bar
|
|
104
|
-
</button>
|
|
105
|
-
<button type="button" style="margin: 4px" @click="scrollTo100px">
|
|
106
|
-
Scroll To 100px
|
|
107
|
-
</button>
|
|
108
|
-
<button type="button" style="margin: 4px" @click="scrollToLarge">
|
|
109
|
-
Scroll To 99999999 (top)
|
|
110
|
-
</button>
|
|
111
|
-
<button type="button" style="margin: 4px" @click="scrollTo50Top">
|
|
112
|
-
Scroll To 50 (top)
|
|
113
|
-
</button>
|
|
114
|
-
<button type="button" style="margin: 4px" @click="scrollTo50Bottom">
|
|
115
|
-
Scroll To 50 (bottom)
|
|
116
|
-
</button>
|
|
117
|
-
<button type="button" style="margin: 4px" @click="scrollTo50Auto">
|
|
118
|
-
Scroll To 50 (auto)
|
|
119
|
-
</button>
|
|
120
|
-
<br>
|
|
121
|
-
<button type="button" style="margin: 4px" @click="scrollTo50TopOffset">
|
|
122
|
-
Scroll To 50 (top) + 15 offset
|
|
123
|
-
</button>
|
|
124
|
-
<button type="button" style="margin: 4px" @click="scrollTo50BottomOffset">
|
|
125
|
-
Scroll To 50 (bottom) + 15 offset
|
|
126
|
-
</button>
|
|
127
|
-
<button type="button" style="margin: 4px" @click="scrollToKey50">
|
|
128
|
-
Scroll To key 50 (auto)
|
|
129
|
-
</button>
|
|
130
|
-
<button type="button" style="margin: 4px" @click="scrollToLast">
|
|
131
|
-
Scroll To Last (top)
|
|
132
|
-
</button>
|
|
133
|
-
<button type="button" style="margin: 4px" @click="scrollToFirst">
|
|
134
|
-
Scroll To First (bottom)
|
|
135
|
-
</button>
|
|
136
|
-
<button type="button" style="margin: 4px" @click="visible = !visible">
|
|
137
|
-
Toggle visible
|
|
138
|
-
</button>
|
|
139
|
-
</div>
|
|
140
|
-
|
|
141
|
-
<VirtualList
|
|
142
|
-
ref="listRef"
|
|
143
|
-
:data="data"
|
|
144
|
-
:height="200"
|
|
145
|
-
:item-height="20"
|
|
146
|
-
item-key="id"
|
|
147
|
-
:style="{
|
|
148
|
-
border: '1px solid red',
|
|
149
|
-
boxSizing: 'border-box',
|
|
150
|
-
display: visible ? '' : 'none',
|
|
151
|
-
}"
|
|
152
|
-
@scroll="onScroll"
|
|
153
|
-
>
|
|
154
|
-
<template #default="{ item }">
|
|
155
|
-
<span
|
|
156
|
-
:style="{
|
|
157
|
-
height: `${30 + (item.id % 2 ? 0 : 10)}px`,
|
|
158
|
-
lineHeight: '30px',
|
|
159
|
-
display: 'inline-block',
|
|
160
|
-
padding: '0 8px',
|
|
161
|
-
}"
|
|
162
|
-
@click="() => console.log('Click:', item.id)"
|
|
163
|
-
>
|
|
164
|
-
{{ item.id }}
|
|
165
|
-
</span>
|
|
166
|
-
</template>
|
|
167
|
-
</VirtualList>
|
|
168
|
-
</div>
|
|
169
|
-
</template>
|
|
170
|
-
|
|
171
|
-
<style scoped>
|
|
172
|
-
button {
|
|
173
|
-
padding: 4px 8px;
|
|
174
|
-
cursor: pointer;
|
|
175
|
-
}
|
|
176
|
-
</style>
|
package/docs/height.vue
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
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>
|