vue路由

87 阅读5分钟

参考文章:

  1. 前端路由简介以及vue-router实现原理
  2. 可能比文档还详细--VueRouter完全指北 (注:本文只是整理和保存个人学习过程,参考文章如上,如侵删)

hash模式

www.xxx.com/#/login

hostory模式

这种模式是目前vue较常用的路由模式,适合用于单页面应用,传统的路由是用一些超链接来实现页面切换和跳转。而vue-router在单页面应用中,则是组件之间的切换。其本质就是:建立并管理url和对应组件之间的映射关系

HTML

首先看html这部分,通常对应项目中的app.vue文件。

  1. router-link组件用例导航,可以理解为a超链接标签(默认会被渲染成a标签);
  2. router-view组件来设置切换的视图渲染;
  <div id="app">
    <keep-alive>
      <!-- 路由匹配到的组件将会在这里渲染 -->
      <router-view v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive"></router-view>
  </div>
</template>

JavaScript

1. 使用
  1. 定义路由
const path = '/projectname';

const routes = [
  {
    path: `${path}/xxx`,
    name: 'xxx',
    component: () => import ('@/pages/A.vue'),
    meta: {
      title: '评论详情',
    },
  },
];
export default routes;
  1. 创建路由实例
const router = new VueRouter({
  mode: 'history', // history模式
  base: __dirname,
  routes,
});
  1. 创建和挂载根实例
new Vue({
  router,
  render: (h) => h(App),
}).$mount('#app');

通过注入路由器,我们可以在任何组件内通过 this.$router 访问路由器,也可以通过 this.$route访问当前路由对象:

2. $router$route

Tips:这里我简单说明下$router$route的区别:

  • $router是指整个路由实例,你可以操控整个路由,通过'$router.push'往其中添加任意的路由对象.
  • $route:是指当前路由实例('$router')跳转到的路由对象;
  • 路由实例可以包含多个路由对象.它们是父子包含关系.
// 跳转至B页面
this.$router.push({ path: 'B', query: { strNo:123} });
this.$router.push({name:'B',params:{strNo:123}})

// 获取url里的参数
urlData = this.$route.query;
this.$route.params.strNo
3. router.replace

router.replace和router.push很像,但实际效果不一样。push是向history里添加新记录,而replace是直接将当前浏览器history记录替换掉!

那最直接的后果是什么呢? 举个例子:

  • 用push方法,页面1跳转到页面2,你使用浏览器的后退可以回到页面1
  • 用replace方法,页面1被替换成页面2,你使用浏览器的后退,此时你回不到页面1,只能回到页面1的前一页,页面0.

那什么时候会用到replace呢? 当你不想让用户回退到之前的页面时,常见于权限验证,验证后就不让用户回退到登录页重复验证。

可以理解为route栈,router.push是往栈里添加,router.replace是先pop弹出当前栈的页面,再push将页面添加至栈中。

4. 别名alias

别名就是一个路由有两个路径.两个路径都能跳转到该路由。举个栗子:你可能大名叫'ee',但你的小名(别名)可能就叫'ff'.但'ee'和'ff'指代的是同一个人(路由). 别名是在rutes里的alias进行配置:

// 路径 /ee 和 /ff 都会跳转到该路由组件
const routes = [
  {
    path: `/ee`,
    component: () => import ('@/pages/yummy/A.vue'),
    alias: '/ff'
  },
];
5. 组件按组分块

组件按组分块可以把路由下的所有组件都打包在同个异步块 (chunk) 中,并且在f12的network里面看到动态加载的组件名字。 前提条件:

  • Webpack版本 > 2.4
  • 需要在webpack.base.conf.js里面的output里面的filename下面加上chunkFileName
output: {
 path: config.build.assetsRoot,
 filename: '[name].js',
 // 需要配置的地方
 chunkFilename: '[name].js',
 publicPath: process.env.NODE_ENV === 'production'
   ? config.build.assetsPublicPath
   : config.dev.assetsPublicPath
}

此时在引入组件时的写法需要使用 命名 chunk,一个特殊的注释语法来提供 chunk name

const A = () => import(/* webpackChunkName: "group-yummy" */ './A.vue')
const B = () => import(/* webpackChunkName: "group-yummy" */ './B.vue')
const C = () => import(/* webpackChunkName: "group-yummy" */ './C.vue')

6. (导航守卫)路由钩子

1,全局守卫: :异步执行,每个路由跳转都会按顺序执行.

  • router.beforeEach 全局前置守卫 router.beforeEach((to, from ,next) => {})
  • router.beforeResolve 全局解析守卫(2.5.0+) 在beforeRouteEnter调用之后调用.
  • router.afterEach 全局后置钩子 进入路由之后 注意:不支持next() ,只能写成这种形式router.afterEach((to, from) => {});
//1,可以在main.js 或者在单独的路由配置文件router.js中进行设置
router.beforeEach((to, from, next) => { 
  ...
  next();
});
	
//2,也可以在组件内部设置
this.$router.beforeEach((to, from, next) => { 
  ...
  next();
});
	
//3,对函数及next()的详细使用说明
router.beforeEach((to, from, next) => { 
	//首先to和from 其实是一个路由对象,所以路由对象的属性都是可以获取到的(具体可以查看官方路由对象的api文档).
	//例如:我想获取获取to的完整路径就是to.path.获取to的子路由to.matched[0].
      next();//使用时,千万不能漏写next!!!
	//next()  表示直接进入下一个钩子.
	//next(false)  中断当前导航
	//next('/path路径')或者对象形式next({path:'/path路径'})  跳转到path路由地址
	//next({path:'/shotcat',name:'shotCat',replace:true,query:{logoin:true}...})  这种对象的写法,可以往里面添加很多.router-link 的 to prop 和 router.push 中的选项(具体可以查看api的官方文档)全都是可以添加进去的,再说明下,replace:true表示替换当前路由地址,常用于权限判断后的路由修改.
	//next(error)的用法,(需2.4.0+) 
    }).catch(()=>{
  //跳转失败页面
  next({ path: '/error', replace: true, query: { back: false }})
})
//如果你想跳转报错后,再回调做点其他的可以使用 router.onError()
router.onError(callback => { 
      console.log('出错了!', callback);
    });

  • 2,路由独享的守卫:  即路由对象独享的守卫

    • beforeEnter:路由只独享这一个钩子,在rutes里配置
  • 3,组件内的守卫: 注意:这类路由钩子是写在组件内部的,

    • beforeRouteEnter 进入路由前,此时实例还没创建,无法获取到zhis
    • beforeRouteUpdate (2.2) 路由复用同一个组件时
    • beforeRouteLeave 离开当前路由,此时可以用来保存数据,或数据初始化,或关闭定时器等等
7. 路由元信息

一句话概括:路由配置的meta对象里的信息

// keepAlive: true 缓存页面A,当页面A跳转至页面B,由B页面返回A页面时,可以不再刷新页面等请求后端等操作
{
    path: `A`,
    component: A,
    meta: {
      title: '标题',
      keepAlive: true,
    },
 },
8. 滚动行为

当年切换路由时,可以使页面滚动到你想要的某个地方,或者是保持之前滚动的位置,这时你就需要使用scrollBehavior这个方法.

const scrollBehavior = (to, from, savedPosition) => {
  if (savedPosition) {
    // savedPosition is only available for popstate navigations.
    return savedPosition;
  }
  const position = {};
  // new navigation.
  // scroll to anchor by returning the selector
  if (to.hash) {
    position.selector = to.hash;
  }
  // check if any matched route config has meta that requires scrolling to top
  if (to.matched.some((m) => m.meta.scrollToTop)) {
    // cords will be used if no selector is provided,
    // or if the selector didn't match any element.
    position.x = 0;
    position.y = 0;
  }
  // if the returned position is falsy or an empty object,
  // will retain current scroll position.
  return position;
};