rework main RouterLink so that only a route with params receives a key

This commit is contained in:
axolotle 2022-02-06 20:57:47 +01:00
parent 43637ea7ae
commit 4531433d60
4 changed files with 39 additions and 6 deletions

View file

@ -40,9 +40,9 @@
<!-- The `key` on router-view make sure that if a link points to a page that <!-- The `key` on router-view make sure that if a link points to a page that
use the same component as the previous one, it will be refreshed --> use the same component as the previous one, it will be refreshed -->
<transition v-if="transitions" :name="transitionName"> <transition v-if="transitions" :name="transitionName">
<router-view class="animated" :key="$route.fullPath" /> <router-view class="animated" :key="routerKey" />
</transition> </transition>
<router-view v-else class="static" :key="$route.fullPath" /> <router-view v-else class="static" :key="routerKey" />
</main> </main>
</view-lock-overlay> </view-lock-overlay>
@ -93,7 +93,13 @@ export default {
}, },
computed: { computed: {
...mapGetters(['connected', 'yunohost', 'transitions', 'waiting']) ...mapGetters([
'connected',
'yunohost',
'routerKey',
'transitions',
'waiting'
])
}, },
watch: { watch: {

View file

@ -29,6 +29,7 @@ const router = new VueRouter({
}) })
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
store.dispatch('UPDATE_ROUTER_KEY', { to, from })
if (store.getters.error) { if (store.getters.error) {
store.dispatch('DISMISS_ERROR', true) store.dispatch('DISMISS_ERROR', true)
} }

View file

@ -167,6 +167,7 @@ const routes = [
component: () => import(/* webpackChunkName: "components/configPanel" */ '@/components/ConfigPanel'), component: () => import(/* webpackChunkName: "components/configPanel" */ '@/components/ConfigPanel'),
props: true, props: true,
meta: { meta: {
routerParams: ['name'], // Override router key params to avoid view recreation at tab change.
args: { trad: 'config' }, args: { trad: 'config' },
breadcrumb: ['domain-list', 'domain-info', 'domain-config'] breadcrumb: ['domain-list', 'domain-info', 'domain-config']
} }
@ -267,6 +268,7 @@ const routes = [
component: () => import(/* webpackChunkName: "components/configPanel" */ '@/components/ConfigPanel'), component: () => import(/* webpackChunkName: "components/configPanel" */ '@/components/ConfigPanel'),
props: true, props: true,
meta: { meta: {
routerParams: ['id'],
args: { trad: 'app_config_panel' }, args: { trad: 'app_config_panel' },
breadcrumb: ['app-list', 'app-info', 'app-config-panel'] breadcrumb: ['app-list', 'app-info', 'app-config-panel']
} }

View file

@ -2,7 +2,7 @@ import Vue from 'vue'
import router from '@/router' import router from '@/router'
import i18n from '@/i18n' import i18n from '@/i18n'
import api from '@/api' import api from '@/api'
import { timeout, isObjectLiteral } from '@/helpers/commons' import { timeout, isEmptyValue, isObjectLiteral } from '@/helpers/commons'
export default { export default {
state: { state: {
@ -15,7 +15,8 @@ export default {
requests: [], // Array of `request` requests: [], // Array of `request`
error: null, // null || request error: null, // null || request
historyTimer: null, // null || setTimeout id historyTimer: null, // null || setTimeout id
tempMessages: [] // array of messages tempMessages: [], // Array of messages
routerKey: undefined // String if current route has params
}, },
mutations: { mutations: {
@ -87,6 +88,10 @@ export default {
} else { } else {
state.error = null state.error = null
} }
},
'SET_ROUTER_KEY' (state, key) {
state.routerKey = key
} }
}, },
@ -264,6 +269,24 @@ export default {
'DISMISS_WARNING' ({ commit, state }, request) { 'DISMISS_WARNING' ({ commit, state }, request) {
commit('SET_WAITING', false) commit('SET_WAITING', false)
Vue.delete(request, 'showWarningMessage') Vue.delete(request, 'showWarningMessage')
},
'UPDATE_ROUTER_KEY' ({ commit }, { to, from }) {
if (isEmptyValue(to.params)) {
commit('SET_ROUTER_KEY', undefined)
return
}
// If the next route uses the same component as the previous one, Vue will not
// recreate an instance of that component, so hooks like `created()` will not be
// triggered and data will not be fetched.
// For routes with params, we create a unique key to force the recreation of a view.
// Params can be declared in route `meta` to stricly define which params should be
// taken into account.
const params = to.meta.routerParams
? to.meta.routerParams.map(key => to.params[key])
: Object.values(to.params)
commit('SET_ROUTER_KEY', `${to.name}-${params.join('-')}`)
} }
}, },
@ -279,6 +302,7 @@ export default {
currentRequest: state => { currentRequest: state => {
const request = state.requests.find(({ status }) => status === 'pending') const request = state.requests.find(({ status }) => status === 'pending')
return request || state.requests[state.requests.length - 1] return request || state.requests[state.requests.length - 1]
} },
routerKey: state => state.routerKey
} }
} }