About this post
on the web page, the progress bar tends to be global component.
And, it is preferred to be opened from TypeScript (not from Vue template using v-if
) because the bar should be opened only while the process.
In this post, the way of implementation about progress bar opened from TypeScript is introduced.
Target readers
- the developers who want to implement
progressbar
by Vue.js or Nuxt.js - the developers who have basics about store and Vuetify.js (some basic parts of store and Vuetify will be omitted.)
Versions
content | version |
---|---|
nuxt | 2.15.8 |
nuxt-typed-vuex | 0.3.0 |
vue | 2.6.14 |
vuetify | 2.6.1 |
the directory structure
sampleProject ├componens | └progressbar.vue ├pages | └index.vue ├store | ├index.ts | └progressbar.ts └types └index.d.ts
Steps to open the progress bar from TypeScript
- the heavy process is executed.
- the store of
progressbar
is called. - while the heavy process is executed, progress bar component is shown thanks to the store of of
progressbar
. - after the heavy process is done, progress bar component is not shown anymore.
Create a store to control progress bar
Create store/progressbar.ts
.
import { mutationTree, actionTree } from 'typed-vuex'; // isShown is to control whether progress bar is shown or not export const state = () => ({ isShown: false as boolean, }); export type RootState = ReturnType<typeof state>; export const mutations = mutationTree(state, { change(state, isShown: boolean) { state.isShown = isShown; }, }); export const actions = actionTree( { state, mutations }, { async open({ commit }, action: Function) { // only while action is executed, the progress bar is opened commit('change', true); try { await action(); } finally { // even if the argument action throws an error, the progress bar should be closed commit('change', false); } }, }, );
Register the store by creating store/index.ts
.
import { getAccessorType, getterTree, mutationTree, actionTree, } from 'typed-vuex'; // if there is other stores, import here import * as progressbar from './progressbar'; export const state = () => ({}); export const getters = getterTree(state, {}); export const mutations = mutationTree(state, {}); export const actions = actionTree({ state, getters, mutations }, {}); export const accessorType = getAccessorType({ state, getters, mutations, actions, modules: { // if there is other stores, add here progressbar, }, });
Extend the types for vue
so that the store can be accessed from the file of vue
extension.
create types/index.d.ts
import { accessorType } from '~~/store'; declare module 'vue/types/vue' { interface Vue { $accessor: typeof accessorType; } }
Create a progress bar component
By the implementation of this.$store.subscribe
, catch the change notification of store progressbar
and change the visibility according to isShown
store value.
<template> <!-- set z-index so that this progress bar can be shown above the modal dialog --> <v-overlay z-index="100" :value="isShown"> <v-progress-circular indeterminate color="primary"></v-progress-circular> </v-overlay> </template> <script lang="ts"> import Vue from 'vue'; export default Vue.extend({ name: 'AppProgressbar', data() { return { isShown: false, }; }, created() { this.$store.subscribe((mutation, state) => { if (mutation.type === 'progressbar/change') { this.isShown = state.progressbar.isShown; } }); }, }); </script>
Open progress bar from TypeScript
Create pages/index.vue
.
Only in the scope of await this.$accessor.progressbar.open(async () => {});
, the progress bar is shown.
<template> <button @click="doHeavyProcess">Execute</button> </template> <script lang="ts"> import Vue from 'vue'; export default Vue.extend({ methods: { async doHeavyProcess() { await this.$accessor.progressbar.open(async () => { // in this scope, the progress bar is shown await this.$axios.get('https://example.com'); }); // out of the scope of progress bar, the progress bar is not shown }, }, }); </script>
Top comments (0)