SOURCE

console 命令行工具 X clear

                    
>
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>