vue3 vue.js infinite-loading-vue3 を無限スクロールを極める


このライブラリは駄目だな。
ライブラリ自体が壊れてるのかスマホで見ると連続で1ページ目を読み込んでしまう。
使わないほうが良い。

# こっちを使おう
https://qiita.com/ma7ma7pipipi/items/2c6049ebedcd42977c04


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>



```