無限スクロール最新版
追記
データが13件のとき、すべてを読み込み、元のページに戻る、リロードをすると同じページを読み込んでしまうのを防止。
hoge.vue
<template>
<h1 class="title">アンサーショー</h1>
<div class="infinite-list-wrapper">
<div>
<div v-infinite-scroll="load" class="list" :infinite-scroll-disabled="disabled" infinite-scroll-distance="150">
<div v-for="(v,key) in infShow" :key="key" style="border-bottom:1px solid #ededed;">
<h2>{{key}} {{v.id}}</h2>
</div>
<p v-if="loading">Loading...</p>
<p v-if="noMore">すべて読み込みました</p>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import {ref, onMounted, inject, reactive} from 'vue';
import axios from 'axios';
import { useStoreUser } from '/resources/user';
const user = useStoreUser();
import {useRoute, useRouter} from 'vue-router';
const route = useRoute()//route.params.id を取得するのに必要
const router = useRouter();
const axiosUrl = ref()
const infShow = ref(reactive([]))
const loading = ref(false)
const noMore = ref(false)
const disabled = ref(false)
const readedUrl = reactive<string[]>([]);
const load = () => {
loading.value = true
setTimeout(() => {
getShow()
loading.value = false
}, 200)
}
const getShow = () => {
if (!readedUrl.includes(axiosUrl.value)) {
readedUrl.push(axiosUrl.value);
if(axiosUrl.value != null){
axios.post(axiosUrl.value)
.then(response => {
router.replace({
path: route.path,
query:{
page: response.data.res.current_page
}
}, () => {}, () => {});
axiosUrl.value = response.data.res.next_page_url;
infShow.value.push(...response.data.res.data);
//ページ遷移対策で、sessionstorageにデータを保存
sessionStorage.setItem(route.name,JSON.stringify(infShow.value));
//最大件数も保存
sessionStorage.setItem(route.name + 'total',JSON.stringify(response.data.res.total));
if(response.data.res.next_page_url == null){
disabled.value = true
noMore.value = true
}
})
.catch(error => {
// エラーを処理する
disabled.value = true
noMore.value = true
console.error(error)
})
}
} else {
console.log("アクシオスurlがreadurlにあります");
}
}
onMounted(() => {
//最初に user_id をつける
let page = 1;
if(route.query.page){
let total = JSON.parse(sessionStorage.getItem(route.name + 'total'));
let savedValue = JSON.parse(sessionStorage.getItem(route.name));
if(Array.isArray(savedValue)) {
savedValue.forEach(item => infShow.value.push(item));
}
//読み込んだデータとトータルの数が同じであれば、それ以上読み込まない
//(ページ遷移時に限界突破して読み込むのを防ぐ)
if(infShow.value.length == total){
disabled.value = true
noMore.value = true
console.log("トータルカウントが同じなのでこれ以上読み込みません。");
}
} else {
sessionStorage.removeItem(route.name);
}
axiosUrl.value = "/answers/show?page=" + route.query.page
console.log("mounted...");
});
</script>
#追記
戻る をした時にデータを復元
最下部の url だけ変更すりゃコピペで動く。
<template>
<div class="infinite-list-wrapper">
<div v-infinite-scroll="load"
class="list"
:infinite-scroll-disabled="disabled"
infinite-scroll-distance="150">
<div
v-for="(v,key) in infShow" :key="key"
:span="12">
<RouterLink :to="{ path: '/'+v.id+'/'}">{{key}} : {{v.id}}</RouterLink>
</div>
</div>
<p v-if="loading" style="background-color: red;">Loading...</p>
<p v-if="noMore">すべて読み込みました</p>
</div>
</template>
<script lang="ts" setup>
import {ref, onMounted,reactive} from 'vue';
import {useRoute, useRouter} from 'vue-router';
import axios from "axios";
const route = useRoute()//route.params.id を取得するのに必要
const router = useRouter();
const axiosUrl = ref()
const infShow = ref(reactive([]))
const loading = ref(false)
const noMore = ref(false)
const disabled = ref(false)
const readedUrl = reactive<string[]>([]);
const load = () => {
loading.value = true
setTimeout(() => {
getShow()
loading.value = false
}, 200)
}
const getShow = () => {
if (!readedUrl.includes(axiosUrl.value)) {
readedUrl.push(axiosUrl.value);
if(axiosUrl.value != null){
axios.post(axiosUrl.value)
.then(response => {
router.push({
path: route.path,
query:{
page: response.data.res.current_page,
}
}, () => {}, () => {});
axiosUrl.value = response.data.res.next_page_url;
infShow.value.push(...response.data.res.data);
sessionStorage.setItem(route.name,JSON.stringify(infShow.value));
if(response.data.res.next_page_url == null){
disabled.value = true
noMore.value = true
}
})
.catch(error => {
// エラーを処理する
disabled.value = true
noMore.value = true
console.error(error)
})
}
}
}
onMounted(() => {
let page = 1;
if(route.query.page){
page = route.query.page;
let savedValue = JSON.parse(sessionStorage.getItem(route.name));
if(Array.isArray(savedValue)) {
savedValue.forEach(item => infShow.value.push(item));
}
} else {
sessionStorage.removeItem(route.name);
}
//url整形
axiosUrl.value = "/questions/show?page=" + page
});
</script>
シンプルに。
同じページ何度も読み込まないようにしてある。
readedUrl.push(axiosUrl.value);
が味噌ですわ。
hoge.vue
<template>
<div class="infinite-list-wrapper">
<el-row v-infinite-scroll="load"
class="list"
:infinite-scroll-disabled="disabled"
infinite-scroll-distance="150">
<el-col
v-for="(v,key) in userShow" :key="key"
:span="12">
<div class="list-item">
<a style="cursor:pointer">{{key}} : {{v.id}} {{v.name}}</a>
</div>
</el-col>
</el-row>
<p v-if="loading" style="background-color: red;">Loading...</p>
<p v-if="noMore">すべて読み込みました</p>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
const child = ref();
const direction = ref('btt')
const size = ref(`100%`)
const lock = ref(true)
const axiosUrl = ref(`/users/show`)
const userShow = ref(reactive([]))
const loading = ref(false)
const noMore = ref(false)
const disabled = ref(false)
const readedUrl = reactive<string[]>([]);
const load = () => {
loading.value = true
setTimeout(() => {
getShow()
loading.value = false
}, 200)
}
const getShow = () => {
if (!readedUrl.includes(axiosUrl.value)) {
readedUrl.push(axiosUrl.value);
console.log("ページを読み込みます" + axiosUrl.value);
if(axiosUrl.value != null){
axios.post(axiosUrl.value)
.then(response => {
console.log(response.data.res);
axiosUrl.value = response.data.res.next_page_url;
userShow.value.push(...response.data.res.data);
if(response.data.res.next_page_url == null){
disabled.value = true
noMore.value = true
}
})
.catch(error => {
// エラーを処理する
disabled.value = true
noMore.value = true
console.error(error)
})
}
}
}
</script>
<style scoped>
.infinite-list-wrapper {
height: 50%;
text-align: center;
}
.infinite-list-wrapper .list {
padding: 0;
margin: 0;
list-style: none;
}
.infinite-list-wrapper .list-item {
display: flex;
align-items: center;
justify-content: center;
height: 150px;
background: var(--el-color-danger-light-9);
color: var(--el-color-danger);
}
.infinite-list-wrapper .list-item + .list-item {
margin-top: 10px;
}
</style>