Infinite scroll with Vue.js2.2
by bc_rikko
HTML
<div id="app">
<p class="debug">{{ debug }}</p>
<div class="item-container" @scroll="infiniteScroll">
<div v-for="item in items" class="item-card">
<div class="thumbnail"></div>
<h3 class="title">{{ item.title }}</h3>
</div>
<div class="loader"><p>Now loading......</p></div>
</div>
</div>
SCSS
body {
background-color: white;
font-size: 62.5%;
padding: 10px;
}
.item-container {
width: 100%;
height: 100vh;
padding: 0 20px;
overflow-y: auto;
}
.item-card {
width: 80%;
height: 80px;
}
.item-card {
display: flex;
margin-bottom: 20px;
> .thumbnail {
background-color: #C7E7EF;
width: 80px;
height: 80px;
}
> .title {
margin-left: 10px;
font-size: 2rem;
color: #00BADD;
}
}
.loader {
width: 100%;
height: 50px;
text-align: center;
position: relative;
overflow: hidden;
&::after {
content: '';
display: block;
width: 100%;
height: 100%;
background-color: white;
position: absolute;
top: 0;
transform: translateX(30%);
animation: loading 1.5s infinite;
}
> p {
font-size: 2rem;
color: #AAAAAA;
}
}
@keyframes loading {
100% {
transform: translateX(70%);
}
}
.debug {
position: fixed;
top: 0;
right: 0;
background-color: rgba(170,170,170,.25);
z-index: 1;
}
JavaScript
// mock
function api (page, limit) {
const items = [...Array(limit)].map((a, i) => {
return {
title: `page: ${page}, limit: ${limit}, ${i.toString().repeat(10)}`
};
});
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(items);
}, 2000);
});
}
const app = new Vue({
el: '#app',
data () {
return {
page: 0,
limit: 10,
items: [],
debug: 'debug'
}
},
async created () {
this.fetch();
},
methods: {
async fetch () {
const items = await api(this.page, this.limit);
this.items.push(...items);
this.page++;
},
infiniteScroll (event) {
this.debug = [
`scrollTop: ${event.target.scrollTop}`,
`offsetHeight: ${event.target.offsetHeight}`,
`scrollHeight: ${event.target.scrollHeight}`,
`content: ${this.items.length}`
].join(' | ');
// スクロールの現在位置 + 親(.item-container)の高さ >= スクロール内のコンテンツの高さ
if ((event.target.scrollTop + event.target.offsetHeight) >= event.target.scrollHeight) {
this.fetch();
}
}
}
})