このライブラリは駄目だな。
ライブラリ自体が壊れてるのかスマホで見ると連続で1ページ目を読み込んでしまう。
使わないほうが良い。
こっちを使おう
vue.js で 無限スクロールをする
すると以下の問題にぶち当たる
・読み込み後に何度も同じページ数を読み込んでしまう
・ページ移動した際に読み込んだデータが消えて再描画が必要
・ブラウザの戻る進むをした際は同じ位置に戻りたい
追記
body に margin:0 とか指定すると動かなくなるので、下手に指定しないほうがいい。
そんなお悩みを解決したのが以下のコード
app.js
const scrollBehavior = (to, from ,savedPosition) => {
if (savedPosition) {
sessionStorage.setItem('positionTop', savedPosition.top);
return savedPosition;
} else {
if (to.hash) {
if(to.hash.indexOf("y-")){
let tmp = to.hash.split('-');
return { top: tmp[1] }
} else {
return { top: 0 }
}
} else {
return { top: 0 }
}
}
};
const router = createRouter({
routes, // short for `routes: routes`
history: createWebHistory(),
scrollBehavior
})
scrollBehavior を読み込む際は別場所に書いておくと良い
InfinitSample.vue
<template>
<div>
<infinite-scroll
@infinite-scroll="loadDataFromServer"
:message="inf.message"
:noResult="inf.noResult"
>
<div>
<div
v-for="v in inf.list"
:key="v.id"
style="margin-bottom: 20px"
>
<div>
<router-link to="/">{{v.id}}</router-link>
</div>
</div>
</div>
</infinite-scroll>
</div>
</template>
<script>
import InfiniteScroll from 'infinite-loading-vue3';
export default {
components: {
InfiniteScroll,
},
data(){
return {
loading:false,
inf: {
query: {
page:1
},
storageName:"infinit_sample",//要変更
list: [],
noResult: false,
message:''
}
}
},
//ページ移動後に、すべてのdomを表示させてから指定の場所に移動する
beforeRouteUpdate(to, from, next) {
if (sessionStorage.getItem('positionTop') === null) {
next();
} else {
var positionTop = sessionStorage.getItem('positionTop');
sessionStorage.removeItem('positionTop');
setTimeout(function(){
scrollTo(0, positionTop);
}, 100);
next();
}
},
mounted() {
if(this.$route.query.page){
console.log("ページ数あるので、以前のを読み込みます(リロード時もこれを経由)");
this.readPageStorage()
} else {
//他の画面を経由して来た場合は検索結果をリセット
console.log("他のページを経由してきたので検索結果をリセットします");
this.clearStorage()
}
this.loadDataFromServer()
},
methods: {
loadDataFromServer(){
try {
if(!this.inf.noResult && !this.loading){
if(!this.$route.query.page){
// console.log("配列からだよ");
this.inf.query.page = 1;
} else {
this.inf.query.page++;
}
this.loading = true;
axios.post('/users/test/',this.inf.query).then(e => {
if(e.data.res.data.length) {
//push にすると うまく動かないのでconcatする
this.inf.list = this.inf.list.concat(e.data.res.data);
this.$router.push({
path: "/"+this.inf.storageName+"/",
hash:"#y-" + document.body.scrollHeight,
query:this.inf.query,
}, () => {}, () => {});
this.addPageStorage();
} else {
this.inf.noResult = true;
this.inf.message = "読み込み完了";
}
console.log(" 成功");
this.loading = false;
}).catch((error) => {
console.log(error);
this.inf.noResult = true;
this.inf.message = "すべてのページを読み込みました";
console.log(" エラー");
//全ページ読み込み時に戻るをしたらもとの位置にもどらないので (beforeRouteUpdateが動かない)
if (sessionStorage.getItem('positionTop') !== null) {
var positionTop = sessionStorage.getItem('positionTop');
sessionStorage.removeItem('positionTop');
setTimeout(function(){
scrollTo(0, positionTop);
}, 100);
}
this.loading = false;
});
}
} catch(err) {
this.inf.noResult = true;
this.inf.message = "ページを読み込めません";
this.loading = false;
}
},
// //現在のページ情報を保存する
addPageStorage() {
sessionStorage.setItem(this.inf.storageName + '_list',JSON.stringify(this.inf.list));
sessionStorage.setItem(this.inf.storageName + '_query',JSON.stringify(this.inf.query));
},
// //戻ってきた場合、ページ情報を復元する
readPageStorage() {
if (sessionStorage.getItem(this.inf.storageName + '_list') === null) {
this.inf.query.page = this.$route.query.page;
} else {
this.inf.list = JSON.parse(sessionStorage.getItem(this.inf.storageName + '_list'));
this.inf.query = JSON.parse(sessionStorage.getItem(this.inf.storageName + '_query'));
}
},
//
// //session storage を 削除。 clear sessionStorage.clear() は使わない。
clearStorage() {
sessionStorage.removeItem(this.inf.storageName + '_list');
sessionStorage.removeItem(this.inf.storageName + '_query');
},
},
}
</script>