Vue Router总结

Vue Router总结

动态路由匹配

  • 我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件

    const User = {
      template: '<div>User</div>'
    }
    
    const router = new VueRouter({
      routes: [
        // 动态路径参数 以冒号开头
        { path: '/user/:id', component: User }
      ]
    })
    
  • 一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用

你可以在一个路由中设置多段“路径参数”,对应的值都会设置到 $route.params 中。例如:

模式匹配路径$route.params
/user/:username/user/evan{ username: 'evan' }
/user/:username/post/:post_id/user/evan/post/123{ username: 'evan', post_id: '123' }

响应路由参数的变化

  • 当使用路由参数时,例如从 /user/foo 导航到 /user/bar原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用

  • 复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route 对象:

    const User = {
      template: '...',
      watch: {
        '$route' (to, from) {
          // 对路由变化作出响应...
        }
      }
    }
    
  • 或者使用 2.2 中引入的 beforeRouteUpdate 导航守卫 :因为是相同组件,所以更新

    const User = {
      template: '...',
      beforeRouteUpdate (to, from, next) {
        // react to route changes...
        // don't forget to call next()
      }
    }
    

匹配优先级

  • 有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高。

  • 当配置 404页面的时候, 当使用通配符路由时,请确保路由的顺序是正确的,也就是说含有通配符的路由应该放在最后。

  • 当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:

    // 给出一个路由 { path: '/user-*' }
    this.$router.push('/user-admin')
    this.$route.params.pathMatch // 'admin'
    // 给出一个路由 { path: '*' }
    this.$router.push('/non-existing')
    this.$route.params.pathMatch // '/non-existing'
    

嵌套路由

  • 要注意,以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。

  • 当你访问 /user/foo 时,User 的出口是不会渲染任何东西,这是因为没有匹配到合适的子路由。如果你想要渲染点什么,可以提供一个 空的 子路由: ‘

    const router = new VueRouter({
      routes: [
        {
          path: '/user/:id', component: User,
          children: [
            // 当 /user/:id 匹配成功,
            // UserHome 会被渲染在 User 的 <router-view> 中
            { path: '', component: UserHome },
    
            // ...其他子路由
          ]
        }
      ]
    })
    

编程式导航

  • 注意:在 Vue 实例内部,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push

  • 想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

  • 当你点击 <router-link> 时,这个方法会在内部调用,所以说,点击 <router-link :to="..."> 等同于调用 router.push(...)

    声明式编程式
    ``router.push(...)
// 字符串
router.push('home')

// 对象
router.push({ path: 'home' })

// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})

// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

注意:如果提供了 pathparams 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path

const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user

router.replace(location, onComplete?, onAbort?)

router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。

声明式编程式
<router-link :to="..." replace>router.replace(...)

#router.go(n)

  • 这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)

// 后退一步记录,等同于 history.back()
router.go(-1)

// 前进 3 步记录
router.go(3)

// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)

Vue-router

多页面体验

  • 新建router.js

    
    
  • app.vue使用 router-view占位符

  • 使用 router-link作为导航按钮 to 必须有~~~~~~~~~!!!!!!!

history 模式

  • 默认是 hash模式,url 使用#后面定位路由,对seo不利,设置history就可以使用 普通url模式

    //router.js
    export default new VueRouter({
    	mode:'history'
    })
    

路由命名

  • 可以给路由设置name,方便router-link跳转

    <router-link :to="{name:'home',params:{userId:123}}"></router-link>
    

动态路由

  • 路由可以携带一些参数,使用this.$router获取

    {path:'/page3/:id',component:page3}
    

参数属性传递

  • 设置props属性,获取路由的变量 就和 普通的属性 传递没什么区别

    {path:'/page3/:id,props:true,component:page3'}
    
    在 vue 文件中使用   {{id}}
    

命名视图

  • 一个组件内部有多个 router-view怎么分配组件呢?比如三栏布局,顶部点击按钮,左侧栏的菜单变化
<template>
  <div id="app"> 
    <router-view/>
    <router-view name="david"/>
  </div>
</template>

routers:[
  {
    path: '/a',        
    components : {
    	defalut:Home,
    	a:List
    }
  },
]

beforeRouteUpdate(to,from,next){}

  • 这个路由钩子 在路由地址栏输入是不会触发的,只有点击切换才行

路由守卫

方法一:定义一个数组用于检测与管理需要登录的页面,全局路由守卫配合本地存储判断是否跳转

import { localTake } from 'common/js/localStore' // 本地存储方法封装

// 全局路由守卫
router.beforeEach((to, from, next) => {
  const nextRoute = ['User', 'Cart', 'GoodsDetail'] // 需要登录的页面
  let isLogin = localTake('userMsg')  // 判断是否登录,本地存储有用户数据则视为已经登录
  // 未登录状态;当路由到 nextRoute 指定页时,跳转至 UserLogIn
  if (nextRoute.indexOf(to.name) >= 0) { // 检测是否登录的页面
    if (!isLogin) { // 如果未登录(本地存储无用户数据),并且要跳到登录页面
      if (from.name === 'UserLogIn') {
        next('/')
        return
      }
    // 登录后,跳到到当前页面
      router.push({
        name: 'UserLogIn',
        params: {redirect: to.fullPath}  
      })
    }
  }
  // 已登录状态;当路由到 UserLogIn 时,跳转至 Home
  if (to.name === 'UserLogIn') {
    if (isLogin) {
      next('/')
      return
    }
  }
  next() // 必须使用 next ,执行效果依赖 next 方法的调用参数
})

export default router

方法二:通过定义to.meta.needLogin(needLogin 为自定义,路由元信息),判断是否需要登录

import Vue from "vue";
import Router from "vue-router";
import Home from "./views/Home.vue";
import Login from "./views/Login.vue";

Vue.use(Router);

const router = new Router({
  mode: "history",
  base: process.env.BASE_URL,
  routes: [
    {
      path: "/",
      name: "home",
      component: Home
    },
    {
      path: "/login",
      name: "login",
      component: Login
    },
    {
      path: "/about",
      name: "about",
      //常见手法加上meta 就可以实现要是没登录 就无法直接进入 about 页面
      meta: {
        auth: true
      },
  //路由懒加载
      component: () =>
        import(/* webpackChunkName: "about" */ "./views/About.vue")
    }
  ]
});

// 路由守卫
router.beforeEach((to, from, next) => {
  if (to.meta.auth) {
    // 需要登录
    const token = localStorage.getItem("token");
    if (token) {
      next();
    } else {
      next({
        path: "/login",
        //登录成功之后,直接重定向到原来进入的页面,对用户友好
        query: { redirect: to.path }
      });
    }
  } else { // 不需要登录验证
    next()
  }
});

export default router;


//在页面中这样处理
this.$store
        .dispatch("login", this.model)
        .then(code => {
          if (code) {
            // 登录成功重定向   这里的 this.$route.query.redirect 对应 上面路由设置的路由守卫  query: { redirect: to.path }
            const path = this.$route.query.redirect || "/";
            this.$router.push(path);
          }
        })
        .catch(error => {
          // 有错误发生或者登录失败
          const toast = this.$createToast({
            time: 2000,
            txt: error.message || error.response.data.message || "登录失败",
            type: "error"
          });
          toast.show();
        });

推荐使用判断路由元信息的方法,代码比较简洁,能更好的维护与管理

router.beforeEach((to, from, next)

to: Route: 即将要进入的目标 路由对象

from: Route: 当前导航正要离开的路由

next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。

在这里插入图片描述
!](https://img-blog.csdnimg.cn/20191207174315985.png)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值