vue3.jsでWordPressを無限スクロールするコードを書いた話.

2024.09.21

Logging

おはようございます.長いので説明は省きますが、これは生成AIと自分との合作みたいなコードです.一度目の指示では上手くコードを生成してくれなかったので何度か壁打ちみたいなことをしました.尚、WordPressと言ってもREST APIとかいうのを使用した奴です.WordPress側でREST APIを有効にしないと上手く機能しませんのであしからず🙇.

そして、このコードはスマホとPCではスクロール位置が違うようになっているサイト用の専用コードです.なので、普通のレスポンシブ対応サイトだったら判断部分を削除してbody対応のコードだけで無限スクロールが可能になります.

因みにこんな事をしなくてもv3-infinite-loadingのライブラリが合ったりします.それを使用するともっと効率的なコードが書けるみたいだけども、自分はvue初心者さんなのでこんな感じになってます.

          <div id='app' class="page">
            <?php if (have_posts()):?>
                <div v-for="post in posts" :key="post.id" class="blogpage">
                  <h3>{{ post.title.rendered }}</h3>
                  <p> {{ formattedDate(post.date) }}</p>
                  <p v-html="post.content.rendered"></p>
                </div>
            <?php endif; ?>                
          </div>    
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/moment@2.30.1/min/moment.min.js"></script>
<script src="<?= get_template_directory_uri() ?>/asset/Infinity.js?<?=time()?>" type="module" ></script>
import { ref, onMounted, onUnmounted, createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';

createApp({
    setup() {

        const posts = ref([]);
        const page = ref(1);
        const loading = ref(false);
        const hasMore = ref(true);

        onMounted(async () => {
            await fetchPosts();

            if (window.innerWidth < 600) {
                window.addEventListener('scroll', handleScroll);
            } else {
                document.querySelector('#app').addEventListener('scroll', handleScroll);
            }

        });

        onUnmounted(() => {
            if (window.innerWidth < 600) {
                document.documentElement.removeEventListener('scroll', handleScroll);
            } else {
                document.querySelector('#app').removeEventListener('scroll', handleScroll);
            }
        });
        const formattedDate = (dateString) => {
            return moment(dateString).format('YYYY年MM月DD日');
        };

        const fetchPosts = async () => {
            if (loading.value || !hasMore.value) return;

            loading.value = true;
            try {
                const response = await axios.get(`/wp-json/wp/v2/posts?page=${page.value}`);
                if (response?.data?.length) {
                    posts.value = [...posts.value, ...response.data];
                    page.value++;
                    hasMore.value = true;
                }else{
                    hasMore.value = false;
                }

            } catch (error) {
                //console.error(error);
            } finally {
                loading.value = false;
            }
        };

        const handleScroll = async () => {
            let scrollHeight = null;
            let clientHeight = null;
            let scrollTop = null;

            if (window.innerWidth < 600) {
                scrollHeight = document.documentElement.scrollHeight;
                clientHeight = document.documentElement.clientHeight;
                scrollTop = document.documentElement.scrollTop;

            } else {
                scrollHeight = document.querySelector('#app').scrollHeight;
                clientHeight = document.querySelector('#app').clientHeight;
                scrollTop = document.querySelector('#app').scrollTop;
            }

            if (scrollTop + clientHeight >= scrollHeight - 100 && hasMore.value) {
                await fetchPosts();
            }
        };
        return { posts, page, loading, hasMore, fetchPosts, handleScroll, formattedDate };
    }

}).mount('#app')

明日へ続く.

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

addEventListener, asset, async, catch, createApp, dateString, document.querySelector, finally, formattedDate, handleScroll, loading.value, mount, onMounted, onUnmounted, removeEventListener, response, response.data, setup, window.addEventListener, window.innerWidth,