路由vue-router

有道云笔记:http://note.youdao.com/s/QPUDHXcm

基础

官方文档:https://router.vuejs.org/zh/guide/

进阶

导航守卫

解析流程
  • 导航被触发
  • 在失活组件里调用 beforeRouteLeave守卫 调用全局的前置 befoeEach
  • (在复用组件里调用 beforeRouteUpdate守卫)
  • 在路由配置里调用 beforeEnter
  • 解析异步路由组件
  • 在被激活组件里调用 beforeRouteEnter守卫
  • 调用全局解析 beforeResolve
  • 导航被确认
  • 调用全局的后置 afterEach
  • 触发DOM更新
  • 调用beforeRouteEnter守卫中传给 next 的回调函数,创建好的组件
  • 实例会作为回调函数得到参数传入
1、全局前置守卫 beforeEach

当一个导航触发时,全局前置守卫 按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。

const router = new VueRouter({...})

router.beforeEach((to, from, next) => {
    // ...
})

参数:

  • to:即将要进入的目标 路由对象
  • from:当前导航正要离开的路由
  • next:Function:一定要调用该方法来 resilve 这个钩子。

next() 进行管道中的下一个钩子。
next(false) 中断当前的导航。
next(’/’) 或者 next( { path:’/’ } ) 跳转到一个不同的地址。当前导航被中断,然后进行一个新的导航 next(error)

例子

router.beforeEach((to, from, next) => {
  if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
  else next()
})
2、全局解析守卫 beforeResolve

和 router.beforeEach 类似。区别是 在导航确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。

验证例子:

router.beforeEach((to, from, next) => {
    console.log('before each invoked');
    if (to.fullPath === '/app') {
    	// next('/login')//不仅可以写字符串还可以是一个对象
    	next({path: '/login', replace})
    } else {
    	next()
    }
});

router.beforeResolve((to, from, next) => {
    console.log("before resolve invoked")
    next();
});

router.afterEach((to, from) =>{
    console.log("after invoked")
})
3、全局后置钩子 afterEach
router.afterEach((to, from) => {
    // ...
})
4、路由独享的守卫 beforeEnter

在路由配置上直接定义

const router = new VueRouter({
    routes: [{
        path: '/foo',
        component: Foo,
        beforeEnter: (to, from, next) => {
            // ...        
        }    
    }]
})
5、组件内的守卫 beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
  • beforeRouteEnter
  • beforeRouteUpdate
  • beforeRouteLeave
const Foo = {
    template: `...`,
    beforeRouteEnter (to, from, next) {
        //在渲染该组件的对应路由被 confirm(确认) 前调用
        //不能!获取组件实例 'this'
        //因为当守卫执行前,组件实例还没被创建   
    },
    beforeRouteUpdate (to, from, next) {
        //在当前路由改变,但是该组件被复用时调用
        //举例,对于一个带有动态参数的路径,/foo/:id,在/foo/1 和 /foo/2 之间跳转时
        //由于会渲染同样的Foo组件,因此组件实例会被复用,而这个钩子就会在这个情况下被调用
        //可以访问组件实例'this'
    },
    beforeRouteLeave (to, from, next) {
        //导航离开该组件的对应路由时调用
        //可以访问组件实例'this'
    }
}

如果 beforeRouteEnter守卫 要访问组件实例,可以通过传一个回调给 next 来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。

 beforeRouteEnter (to, from, next) {
  next(vm => {
    // 通过 `vm` 访问组件实例
  })
}

这个 beforeRouteLeave守卫 通常用来禁止用户在还未保存修改前突然离开,该导航可以通过 next(false) 来取消

beforeRouteLeave (to, from, next) {
  const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
  if (answer) {
    next()
  } else {
    next(false) 
  }
}

路由元信息

定义路由的时候可以配置 meta 字段:添加自定义数据

官方实例:

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      children: [
        {
          path: 'bar',
          component: Bar,
          // a meta field
          meta: { requiresAuth: true }
        }
      ]
    }
  ]
})

// 下面例子展示在全局导航守卫中检查元字段:
router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    // this route requires auth, check if logged in
    // if not, redirect to login page.
    if (!auth.loggedIn()) {
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next() // 确保一定要调用 next()
  }
})

实例:参考:https://www.cnblogs.com/-xiao/p/11126064.html

//route
meta: { title:'关于' }
// 获取数据的两种方式:
// 1、
 $route.meta.xxxx 
 
 //2、路由前置守卫router.beforeEach 中获取 meta 中的 title 数据,并设置为页面标题
 router.beforeEach((to,from,next)=>{
  // && 与运算 有时可以代替用来代替if 如果前一个值为 true ,则返回后面那个值
   to.meta && setTitle(to.meta.title)
})

export const setTitle = (title) => {
  // 如果该路由没有设置title值,则前一个是 undefined || 前一个值为false时直接返回admin
  // console.log(window.document);
  window.document.title = title || 'admin'
}

获取数据

假设我们有一个 Post 组件,需要基于 $route.params.id 获取文章数据

<template>
  <div class="post">
    <div v-if="loading" class="loading">
      Loading...
    </div>

    <div v-if="error" class="error">
      {{ error }}
    </div>

    <div v-if="post" class="content">
      <h2>{{ post.title }}</h2>
      <p>{{ post.body }}</p>
    </div>
  </div>
</template>
1、导航完成后获取数据

这种方式会马上导航 和 渲染组件,然后在组件的 created 钩子 中获取数据。
这让我们有机会在数据获取期间展示一个 loading 状态,还可以在不同视图间展示不同的 loading 状态。

export default {
  data () {
    return {
      loading: false,
      post: null,
      error: null
    }
  },
  created () {
    // 组件创建完后获取数据,
    // 此时 data 已经被 observed 了
    this.fetchData()
  },
  watch: {
    // 如果路由有变化,会再次执行该方法
    '$route': 'fetchData'
  },
  methods: {
    fetchData () {
      this.error = this.post = null
      this.loading = true
      // replace getPost with your data fetching util / API wrapper
      getPost(this.$route.params.id, (err, post) => {
        this.loading = false
        if (err) {
          this.error = err.toString()
        } else {
          this.post = post
        }
      })
    }
  }
}
2、导航完成前获取数据

这种方式在导航转入新的路由前获取数据。可以在接下来的组件的 beforeRouteEnter守卫 中获取数据,当数据获取成功后只调用 next 方法。

export default {
  data () {
    return {
      post: null,
      error: null
    }
  },
  beforeRouteEnter (to, from, next) {
    getPost(to.params.id, (err, post) => {
      next(vm => vm.setData(err, post))
    })
  },
  // 路由改变前,组件就已经渲染完了
  // 逻辑稍稍不同
  beforeRouteUpdate (to, from, next) {
    this.post = null
    getPost(to.params.id, (err, post) => {
      this.setData(err, post)
      next()
    })
  },
  methods: {
    setData (err, post) {
      if (err) {
        this.error = err.toString()
      } else {
        this.post = post
      }
    }
  }
}

在为后面的视图获取数据时,用户会停留在当前的界面,因此建议在数据获取期间,显示一些进度条或者别的指示。如果数据获取失败,同样有必要展示一些全局的错误提醒。

滚动行为

使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。

// 当创建一个 Router 实例,你可以提供一个 scrollBehavior 方法:

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // return 期望滚动到哪个的位置
  }
})

详情看官网:https://router.vuejs.org/zh/guide/advanced/scroll-behavior.html#%E5%BC%82%E6%AD%A5%E6%BB%9A%E5%8A%A8

路由懒加载

const Foo = () => import('./Foo.vue')

const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值