LoginSignup
1
1

More than 1 year has passed since last update.

Vue3のProviderパターン

Last updated at Posted at 2023-04-20

Vue3のProviderパターンは、typescript環境は結構見かけたのだが
javascript環境でのはあまり見つからず、
試しに作ったローディングスピナーをメモとして残しておく

ちなみにLoadingSpinner.vueのCSSはタグだけ書いて
chatGPTにCSSだけいいように出力してもらったものなので注意

ディレクトリ構成

├ components
| └ LoadingSpinner
|    ├ LoadingSpinner.vue
|    └ loadingStore.js
├ App.vue
└ Chilled.vue

各ファイルのソース

LoadingSpinner.vue
<template>
    <div v-if="store.isActive() === true">
        <div id="loading-overlay" class="loading-overlay">
            <div class="loading-spinner"></div>
        </div>
    </div>
</template>

<script setup>
import {inject} from 'vue'

import {key} from "./loadingStore.js"
const store = inject(key);

</script>
<style scoped>

/* ローディングスピナーとオーバーレイのスタイル */
.loading-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 999;
}

.loading-spinner {
    display: inline-block;
    width: 50px;
    height: 50px;
    border: 3px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    border-top-color: #fff;
    animation: spin 1s ease-in-out infinite;
    -webkit-animation: spin 1s ease-in-out infinite;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

@-webkit-keyframes spin {
    to {
        -webkit-transform: rotate(360deg);
    }
}
</style>
loadingStore.js
import {ref} from 'vue'

const state = ref(false)
const hide = () => {
    state.value = false;
};

const show = () => {
    state.value = true;
};

const isActive = () => {
    return state.value;
};

export const store = {
    state,
    hide,
    show,
    isActive
}

export const key = Symbol('LoadingSpinner')
App.vue
<template>
    <div>
        <Chilled></Chilled>
        <LoadingSpinner/>
    </div>
</template>

<script setup>
import {provide} from "vue";
import Chilled from './Chilled.vue'
import LoadingSpinner from './components/LoadingSpinner/LoadingSpinner.vue'
import {key, store} from './components/LoadingSpinner/loadingStore'

provide(key, store);

</script>

<style scoped>

</style>
Chilled.vue
<template>
    <div>
        <button @click="handleClick">ローディング</button>
    </div>
</template>

<script setup>
import {inject} from 'vue';
import {key} from './components/LoadingSpinner/loadingStore'

const loadingStore = inject(key);
const sleep = (second) => new Promise(resolve => setTimeout(resolve, second * 1000))

const handleClick = async () => {
    loadingStore.show();
    await sleep(2);      //2秒間だけsleep
    loadingStore.hide();
}

defineExpose({
    handleClick
});
</script>
1
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
1
1