I'm trying to implement virtual scrolling behavior using vue-virtual-scroller library. First off, I tried to use 'useVirtualList' component from VueUse library, but I couldn't find my way in there. Then I moved on trying vue-virtual-scroller. I couldn't implement vue-virtual-scroller by looking examples on its docs.
I'll drop 2 code blocks. Each of which contains a component. One of them is a post component. Other one is the parent component called 'HomeView'. As you can see I created a PostService file under the services folder. It fetches data from API I created. The endpoint sends 1000 post objects. I couldn't find my way in implementing virtual list or virtual scrolling for performant rendering like we see on Twitter. I want to render posts vertically.
UserPost.vue:
<script setup>
defineProps({
post: {
type: Object,
required: true,
},
})
const MAX_CONTENT_LENGTH = 300
const truncateText = (text) => {
if (text.length > MAX_CONTENT_LENGTH) {
return text.substring(0, MAX_CONTENT_LENGTH) + "..."
} else {
return text
}
}
</script>
<template>
<div class="post">
<div class="post__header">
<img :src="post.avatar" class="post__author-logo" />
<div class="post__author-name">{{ post.name }}</div>
<div class="post__author-slug">{{ post.username }}</div>
<div class="post__publish-time">{{ post.publishTime }}</div>
</div>
<div class="post__main">
<h3 class="post__title">{{ post.postTitle }}</h3>
<div class="post__content">{{ truncateText(post.content) }}</div>
</div>
</div>
</template>
<style>
.post {
width: 728px;
margin-bottom: 8px;
border-bottom: 1px solid rgb(117, 117, 117);
}
.post__header {
display: flex;
align-items: center;
margin-bottom: 8px;
}
.post__author-logo {
height: 24px;
width: 24px;
}
.post__author-logo,
.post__author-name,
.post__author-slug,
.post__publish-time {
padding: 4px;
}
.post__author-slug,
.post__publish-time {
color: rgb(117, 117, 117);
}
.post__author-slug::after {
content: "•";
padding-left: 4px;
}
.post__main {
margin-bottom: 8px;
}
.post__title {
font-weight: 700;
font-size: 20px;
}
.post__content {
padding: 8px 0;
font-weight: 400;
line-height: 140%;
}
</style>
HomeView.vue:
<script setup>
import { ref, onMounted } from "vue"
import NavBar from "../components/NavBar.vue"
import UserPost from "../components/UserPost.vue"
import PostService from "../services/PostService"
const posts = ref(null)
onMounted(() => {
PostService.getPosts()
.then((response) => {
posts.value = response.data
})
.catch((error) => {
console.log(error)
})
})
</script>
<template>
<NavBar />
<div class="posts">
<UserPost v-for="post in posts" :key="post._id" :post="post" />
</div>
</template>
<style scoped>
.posts {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 40px;
}
</style>