Skip to content

Commit e3c9922

Browse files
add: 感觉还是有点不清晰
1 parent 5aecd2f commit e3c9922

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
<template>
2+
<div
3+
class="lan-viewport"
4+
ref="viewport"
5+
@scroll="handleViewportScroll"
6+
>
7+
<div
8+
class="lan-scrollBar"
9+
ref="scrollBar"
10+
></div>
11+
<div
12+
class="lan-scroll-list"
13+
:style="{transform:`translate3d(0, ${offset}px, 0)`}"
14+
>
15+
<div
16+
v-for="(item) in visibleData"
17+
:key="item.id"
18+
:vid="item.index"
19+
ref="items"
20+
>
21+
<slot :item="item"></slot>
22+
</div>
23+
</div>
24+
</div>
25+
</template>
26+
27+
<script>
28+
29+
export default {
30+
components: {},
31+
data() {
32+
return {
33+
34+
};
35+
},
36+
props: {
37+
titleInfos: {
38+
type: Object,
39+
default: () => {
40+
return {};
41+
}
42+
},
43+
},
44+
computed: {
45+
prevCount() {
46+
return Math.min(this.start, this.remain)
47+
},
48+
nextCount() {
49+
return Math.min(this.items.length - this.end, this.remain)
50+
},
51+
formatData() {
52+
return this.items.map((item, index) => ({ ...item, index }))
53+
},
54+
visibleData() {
55+
let start = this.start - this.prevCount
56+
let end = this.end + this.nextCount
57+
return this.formatData.slice(start, end)
58+
}
59+
},
60+
mounted() {
61+
this.$refs.viewport.style.height = this.remain * this.size + 'px' // 设置viewPrort的高度
62+
this.$refs.scrollBar.style.height = this.items.length * this.size + 'px' // 设置滚动条高度
63+
this.end = this.start + this.remain // 计算显示范围
64+
if (this.variable) { // 表示高度不定
65+
this.initPosition()
66+
}
67+
},
68+
watch: {},
69+
methods: {
70+
handleViewportScroll() {
71+
let scrollTop = this.$refs.viewport.scrollTop
72+
if (this.variable) {
73+
this.start = this.getStartIndex(scrollTop) // 算出开始的位置
74+
this.end = this.start + this.remain
75+
this.offset = this.positions[this.start - this.prevCount] ? this.positions[this.start - this.prevCount].top : 0
76+
}
77+
},
78+
initPosition() { // 初始化位置
79+
this.positions = this.items.map((item, index) => ({
80+
index,
81+
height: this.size,
82+
top: index * this.size,
83+
bottom: (index + 1) * this.size
84+
}))
85+
},
86+
getStartIndex(value) {
87+
let start = 0
88+
let end = this.positions.length
89+
let temp = null
90+
while (start < end) {
91+
let middleIndex = parseInt((start + end) / 2)
92+
let middleValue = this.positions[middleIndex].bottom
93+
if (value == middleValue) {
94+
return middleIndex + 1
95+
} else if (middleValue < value) {
96+
start = middleIndex + 1
97+
} else if (middleValue > value) {
98+
if (temp == null || temp > middleIndex) {
99+
temp = middleIndex
100+
}
101+
end = middleIndex - 1
102+
}
103+
}
104+
return temp
105+
}
106+
},
107+
updated() {
108+
this.$nextTick(() => { // 获取真实元素的位置 更新top和bottom
109+
if (this.positions.length === 0) return
110+
let nodes = this.$refs.items
111+
if (!(nodes && nodes.length > 0)) {
112+
return
113+
}
114+
nodes.forEach(node => {
115+
let rect = node.getBoundingClientRect()
116+
let height = rect.height
117+
let index = +node.getAttribute('vid')
118+
let oldHeight = this.positions[index].height
119+
let val = oldHeight - height
120+
if (val) {
121+
// 先更新自己
122+
this.positions[index].bottom = this.positions[index].bottom - val
123+
this.positions[index].height = height
124+
for (let i = index + 1; i < this.positions.length; i++) { // 再更新后续兄弟
125+
this.positions[i].top = this.positions[i - 1].bottom
126+
this.positions[i].bottom = this.positions[i].bottom - val
127+
}
128+
}
129+
})
130+
this.$refs.scrollBar.style.height = this.positions[this.positions.length - 1].bottom + 'px'
131+
// this.offset = this.positions[this.start - this.prevCount]? this.positions[this.start - this.prevCount].top : 0
132+
})
133+
},
134+
mounted() {
135+
136+
},
137+
}
138+
139+
</script>
140+
<style lang='scss' scoped>
141+
</style>

0 commit comments

Comments
 (0)