I would like to share with you an alternative that I developed to join the vue-router and the Onsen navigator.
I have not yet integrated 100% with all the features of the vue-router, but it is already possible to navigate between the routes managing the stack navigation.
Based on Kitchensink (https://github.com/OnsenUI/vue-onsenui-kitchensink/blob/master/src/store.js), I created my navigation store too.
export default {
strict: true,
namespaced: true,
state: {
goingBack: false, // Its used when user click on back button
stack: [],
options: {
animation: 'slide'
}
},
mutations: {
push (state, page) {
state.stack.push(page)
},
pop (state) {
state.goingBack = false
if (state.stack.length > 1) {
state.stack.pop()
}
},
replace (state, page) {
state.stack.pop()
state.stack.push(page)
},
reset (state, page) {
state.goingBack = false
state.stack = [page || state.stack[0]]
},
options (state, newOptions = {}) {
state.options = newOptions
},
toggleGoingBack (state, shouldGoingBack) {
if (typeof shouldGoingBack === 'boolean') {
state.goingBack = shouldGoingBack
} else {
state.goingBack = !state.goingBack
}
}
}
}
I used goingBack
to router knows when the user is using a route with same level but is going back.
And my app component is:
<template lang="pug">
v-ons-splitter
v-ons-splitter-side(swipeable collapse="" width="260px"
:open.sync="splitterIsOpen")
menu-page
v-ons-splitter-content
v-ons-navigator(
:page-stack="pageStack"
:pop-page="storePop"
:options="options")
</template>
<script>
import MenuPage from './pages/Menu'
export default {
computed: {
pageStack () {
return this.$store.state.navigator.stack
},
options () {
return this.$store.state.navigator.options
},
splitterIsOpen: {
get () {
return this.$store.state.splitter.open
},
set (newValue) {
this.$store.commit('splitter/toggle', newValue)
}
}
},
methods: {
storePop () {
this.$store.commit('navigator/toggleGoingBack')
if (window.history.length <= 2) {
this.$router.push({ name: 'home' })
} else {
this.$router.go(-1)
}
}
},
components: {
MenuPage
}
}
</script>
And after this, I need to tell the router how his work will stack navigation:
import Vue from 'vue'
import Router from 'vue-router'
import store from '@/store'
import HomePage from '@/pages/Home'
import HostPage from '@/pages/Host'
import HostItemPage from '@/pages/HostItem'
Vue.use(Router)
const router = new Router({
routes: [
{ path: '/', name: 'home', component: HomePage },
{
path: '/host/:profile?',
name: 'host',
component: HostPage,
children: [
{
path: 'items/:item?',
name: 'host-item',
component: HostItemPage
}
]
}
]
})
router.beforeEach((to, from, next) => {
store.commit('splitter/toggle', false)
// When user access root path, clear stack before ends request
if (to.path === '/') {
store.commit('navigator/reset', HomePage)
return next()
}
// Every time when stack is empty, push `HomePage` as first
if (store.state.navigator.stack.length <= 0) {
store.commit('navigator/push', HomePage)
}
// Based on https://github.com/vuejs/vue-router/blob/dev/examples/transitions/app.js#L21
const toDepth = to.path.split('/').length
const fromDepth = from.path.split('/').length
if (from.name && (toDepth < fromDepth || store.state.navigator.goingBack)) {
store.commit('navigator/pop')
} else {
if (toDepth === fromDepth) {
const item = to.matched[to.matched.length - 1]
store.commit('navigator/push', item.components['default'])
} else {
store.commit('navigator/reset')
to.matched.forEach((item) => {
store.commit('navigator/push', item.components['default'])
})
}
}
next()
})
export default router