console
const Home = { template: '<div>home</div>' }
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
function guardRoute (to, from, next) {
if (window.confirm(`您确定要导航至 ${to.path}?`)) {
next()
} else if (window.confirm(`您确定要重定向到 /baz?`)) {
next('/baz')
} else {
next(false)
}
}
// Baz 实现了一个未保存的 beforeRouteLeave 钩子方法
const Baz = {
data () {
return { saved: false }
},
template: `
<div>
<p>baz ({{ saved ? '已保存' : '未保存' }})<p>
<button @click="saved = true">保存</button>
</div>
`,
beforeRouteLeave (to, from, next) {
if (this.saved || window.confirm('数据未保存,你是否要离开?')) {
next()
} else {
next(false)
}
}
}
// Baz 实现了 beforeRouteEnter 钩子
const Qux = {
data () {
return {
msg: null
}
},
template: `<div>{{ msg }}</div>`,
beforeRouteEnter (to, from, next) {
// enter 钩子无法访问目标组件的this,因为组件还没创建
// 但是我们可以提供一个next的回调,当路由确认后能接收vm
// 模拟异步的数据获取,
// 当你想在获取数据后再导航到目标组件时,这种模式是最适合的了。
setTimeout(() => {
next(vm => {
vm.msg = 'Qux'
})
}, 2000)
}
}
// Quux 实现了 beforeRouteUpdate 钩子.
// 当路由变化了,但调用的是同一个组件,组件被重用的时候,这个钩子会被调用,
// 比如,当在 /quux/1 和 /quux/2 之间导航时.
const Quux = {
data () {
return {
prevId: 0
}
},
template: `<div>id:{{ $route.params.id }} prevId:{{ prevId }}</div>`,
beforeRouteUpdate (to, from, next) {
this.prevId = from.params.id
next()
}
}
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/', component: Home },
// 导航前提醒
{ path: '/foo', component: Foo, beforeEnter: guardRoute },
// 在路由配置里,使用了元信息meta,并且在全局钩子里检查meta
{ path: '/bar', component: Bar, meta: { needGuard: true }},
// Baz 实现了beforeRouteLeave钩子
{ path: '/baz', component: Baz },
// Qux 实现了beforeRouteEnter钩子
{ path: '/qux', component: Qux },
// beforeRouteEnter钩子导航到异步组件
{ path: '/qux-async', component: resolve => {
setTimeout(() => {
resolve(Qux)
}, 0)
} },
// beforeRouteUpdate钩子
{ path: '/quux/:id', component: Quux }
]
})
router.beforeEach((to, from, next) => {
if (to.matched.some(m => m.meta.needGuard)) {
guardRoute(to, from, next)
} else {
next()
}
})
new Vue({
router,
el:'#app'
}).$mount('#app')
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.1.6/vue-router.js"></script>
<div id="app">
<h1>导航钩子</h1>
<ul>
<li><router-link to="/">/</router-link></li>
<li><router-link to="/foo">/foo</router-link></li>
<li><router-link to="/bar">/bar</router-link></li>
<li><router-link to="/baz">/baz</router-link></li>
<li><router-link to="/qux">/qux</router-link></li>
<li><router-link to="/qux-async">/qux-async</router-link></li>
<li><router-link to="/quux/1">/quux/1</router-link></li>
<li><router-link to="/quux/2">/quux/2</router-link></li>
</ul>
<router-view class="view"></router-view>
</div>