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)