Suspenseにさわる
Suspenseとは?
コンポーネントを非同期で読み込むための機能らしい。 非同期で読み込む部分を<Suspense>でラップし、読み込むコンポーネントを<template #default>に定義し、フォールバックコンテンツを<template #fallback>に定義する
service/UserService.ts
/* eslint-disable require-jsdoc */ import axios from 'axios'; export interface IUser { id: number, name: string; } export class UserService { public static async getUsers(): Promise<IUser[]> { console.log('### UserService#getUsers() called.'); const response = await axios.get('/api/v1/users/'); const users = response && response.data && response.data.users ? response.data.users : []; return users as IUser[]; } public static async getUser(id: string): Promise<IUser> { console.log('### UserService#getUser() called.'); const response = await axios.get('/api/v1/users/' + id); const user = response && response.data ? response.data : {}; return user as IUser; } }
store/UserStore.ts
import {reactive, inject, provide} from 'vue'; import {UserService, IUser} from '@/service/UserService'; const key = Symbol(); export interface IUserStore { state: { users: IUser[] }, updateState: () => void, updateStateIfEmpty: () => void } const createStore = () => { const state = reactive({ users: [] as IUser[], }); const updateState = async () => { console.log('### UserStore#updateState() called.'); const users: Array<IUser> = await UserService.getUsers(); state.users = users; }; const updateStateIfEmpty = async () => { console.log('### UserStore#updateStateIfEmpty() called.'); if (state.users.length == 0) { await updateState(); } }; return { state, updateState, updateStateIfEmpty, }; }; export const provideStore = () => { console.log('### UserStore#provideStore() called.'); provide(key, createStore()); }; export const useStore = (): IUserStore => { console.log('### UserStore#useStore() called.'); return inject(key) as IUserStore; };
components/UserList.vue
<template lang="pug"> div ul li(v-for="user in state.users" :key="user.userId") {{user.userName}} button(@click="updateState") reload </template> <script lang="ts"> import {defineComponent} from 'vue'; import {useStore} from '@/store/UserStore'; export default defineComponent({ name: 'UserList', async setup() { console.log('### UserList#setup() called.'); const {state, updateState, updateStateIfEmpty} = useStore(); await updateStateIfEmpty(); return { state, updateState, updateStateIfEmpty, }; }, }); </script>
views/UserListPage.vue
<template> <div> <Suspense> <template #default> <UserList /> </template> <template #fallback> <p>Loading...</p> </template> </Suspense> </div> </template> <script lang="ts"> import {defineComponent} from 'vue'; import {provideStore} from '@/store/UserStore'; import UserList from '@/components/UserList.vue'; export default defineComponent({ name: 'UserListPage', components: { UserList, }, setup() { provideStore(); }, }); </script>
はまった点
はじめ<Suspense>を定義するテンプレートをpug化していたが、うまく動作しなかった・・・・pug化を止めたらちゃんと動作した