2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-01-04

このライブラリは駄目だな。
ライブラリ自体が壊れてるのかスマホで見ると連続で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>



2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?