0
0

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 element plus 無限スクロール

Last updated at Posted at 2023-07-09

無限スクロール最新版

追記

データが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>

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?