console
Vue.component('play-list',{
template: "#play-list",
props: ['data'],
data() {
return {
start: 0,
amount: 0,
ob: null,
lineHeight: 70
}
},
mounted() {
this.ob = new ResizeObserver(entries=>{
let containerHeight = entries[0].contentRect.height;
let amount = Math.floor(containerHeight / this.lineHeight)+2;
this.amount = amount;
});
this.ob.observe(this.$el);
},
computed: {
visibleLines() {
if(this.data instanceof Array) {
let start = this.start;
let end = this.start + this.amount;
return this.data.slice(start,end);
}
return [];
},
totalHeight() {
if(this.data instanceof Array) {
return {
height: `${this.data.length * this.lineHeight}px`,
width: 0
}
}
},
linesTop() {
return {
top: `${this.start * this.lineHeight}px`
}
}
},
methods: {
cmpStart(e) {
let scrollTop = e.target.scrollTop;
let start = Math.floor(scrollTop / this.lineHeight);
this.start = start;
}
},
beforeDestroyed() {
this.ob.unobserve(this.$el);
}
})
let data = {"song":"嘉宾","songId":1846489646,"album":"嘉宾","albumId":127728498,"albumCover":"https://p1.music.126.net/LoVqPgkI7DwSNZk50gcODg==/109951165994863998.jpg","duration":"04:30","time":270602,"artists":"路飞文","avail":true}
let vm = new Vue({
el: "#root",
data: {
list: []
}
})
for(let i = 0; i < 1000; ++i) {
let item = Object.create(data);
item.artists += i;
vm.list.push(item);
}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=, initial-scale=">
<meta http-equiv="X-UA-Compatible" content="">
<title></title>
</head>
<body>
<div id="root">
<play-list :data="list"></play-list>
</div>
<template id="play-list">
<div class="play-list">
<div class="row-list scrollbar" @scroll="cmpStart($event)">
<div class="row-wrapper" :style="linesTop">
<div class="row" v-for="(item,index) in visibleLines" :key="index">
<div class="left">
<div class="song">{{item.song}}</div>
<div class="artists">{{item.artists}}</div>
</div>
<div class="right">
<div class="duration">{{item.duration}}</div>
</div>
</div>
</div>
<div class="total-height" :style="totalHeight"></div>
</div>
</div>
</template>
</body>
</html>
* {
margin: 0;
padding: 0;
}
.scrollbar {
overflow: auto !important;
}
.scrollbar::-webkit-scrollbar {
width: 8px;
height: 8px;
}
.scrollbar::-webkit-scrollbar-thumb {
border-radius: 4px;
background: #ccc;
}
#root {
width: 250px;
height: 500px;
background: #fff;
box-shadow: 0 0 5px rgba(0, 0, 0, .3);
}
.play-list {
position: relative;
width: 100%;
height: 100%;
min-width: max-content;
}
.play-list .row-list {
position: relative;
width: 100%;
height: 100%;
}
.play-list .row-list .row-wrapper {
position: absolute;
left: 0;
top: 0;
width: 100%;
}
.play-list .row-list .row {
position: relative;
width: 100%;
height: 70px;
box-sizing: border-box;
}
.play-list .row-list .row:hover {
background: #ddd;
}
.play-list .row-list .row .left {
position: absolute;
left: 10px;
top: 10px;
}
.play-list .row-list .row .right {
position: absolute;
right: 0;
bottom: 15px;
padding-right: 10px;
}
.play-list .row-list .row .song {
font-size: 14px;
}
.play-list .row-list .row .artists,
.play-list .row-list .row .duration {
font-size: 13px;
color: #999;
}
.play-list .row-list .row .artists {
padding-top: 10px;
}