参考文章:
- 前端路由简介以及vue-router实现原理
- 可能比文档还详细--VueRouter完全指北 (注:本文只是整理和保存个人学习过程,参考文章如上,如侵删)
hash模式
hostory模式
这种模式是目前vue较常用的路由模式,适合用于单页面应用,传统的路由是用一些超链接来实现页面切换和跳转。而vue-router在单页面应用中,则是组件之间的切换。其本质就是:建立并管理url和对应组件之间的映射关系
HTML
首先看html这部分,通常对应项目中的app.vue文件。
- router-link组件用例导航,可以理解为a超链接标签(默认会被渲染成a标签);
- 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. 使用
- 定义路由
const path = '/projectname';
const routes = [
{
path: `${path}/xxx`,
name: 'xxx',
component: () => import ('@/pages/A.vue'),
meta: {
title: '评论详情',
},
},
];
export default routes;
- 创建路由实例
const router = new VueRouter({
mode: 'history', // history模式
base: __dirname,
routes,
});
- 创建和挂载根实例
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;
};