🌈个人主页:前端青山
🔥系列专栏:Vue篇
🔖人终将被年少不可得之物困其一生
依旧青山,本期给大家带来vue篇专栏内容:Vue-Router路由
目录
Vue-Router路由
1、路由的概念
2、前端路由实现
3、Vue Router
3.1、介绍
3.2、路由模式切换
3.3、导航方式
3.3.1、声明式导航
3.3.2、编程式导航
3.4、路由重定向
3.5、嵌套路由
3.6、404路由
3.7、路由参数
3.8、路由元信息
Vue-Router路由
1、路由的概念
路由的本质就是一种对应关系
(此处的路由含义同之前nodejs的路由),根据不同的URL请求,返回对应不同的资源。那么url地址和真实的资源之间就有一种对应的关系,就是路由。
路由分为:后端路由
和前端路由
-
后端路由:由服务器端进行实现并实现资源映射分发(nodejs、jsp、php等)
-
概念:根据不同的用户URL请求,返回不同的内容(地址与资源产生对应关系)
-
本质:URL请求地址与服务器资源之间的对应关系(映射)
-
-
前端路由:根据不同的事件来显示不同的页面内容,是事件与事件处理函数之间的对应关系
-
概念:根据不同的用户事件,显示不同的页面内容(地址与事件产生对应关系)
-
本质:用户事件与事件处理函数之间的对应关系
-
记住一句话:有请求就应该有响应,只不过区别在于,之前node是响应资源,现在在前端中通过事件来进行响应。
2、前端路由实现
核心思想:通过监听地址栏的变化事件来实现资源的动态显示
前端路由有2种模式:
-
hash模式
hash路由模式是这样的:http://xxx.abc.com/#/xx。 有带#号,后面就是hash值的变化。改变后面的hash值,它不会向服务器发出请求,因此也就不会刷新页面。并且每次hash值发生改变的时候,会触发hashchange事件。因此我们可以通过监听该事件,来知道hash值发生了哪些变化。
window.addEventListener('hashchange', ()=>{
// 通过 location.hash 获取到最新的 hash 值
console.log(location.hash);
});
-
history模式
形如:http://xxx.abc.com/xx/yy/zz。HTML5的History API为浏览器的全局history对象增加了该扩展方法。它是一个浏览器(bom)的一个接口,在window对象中提供了onpopstate事件来监听历史栈的改变,只要历史栈有信息发生改变的话,就会触发该事件。
history.pushState({},title,url); // 向历史记录中追加一条记录
history.replaceState({},title,url); // 替换当前页在历史记录中的信息。
window.addEventListener('popstate', function(event) {
console.log(event)
})
注:浏览器地址没有#, 比如(http://localhost:3001/a); 它也一样不会刷新页面的。但是url地址会改变。但它在服务器没有配置的情况下,不能手动刷新,否则返回404页面
3、Vue Router
网址:Vue Router | Vue.js 的官方路由
vuerouter是vue全家桶(vue+vue router+vuex )之一。
vue周边生态软件、工具
此处建议创建一个带Router的vue项目。
3.1、介绍
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:
-
嵌套的路由(套娃,父子路由)
-
模块化的、基于组件的路由配置
-
路由参数、查询、通配符
-
带有自动激活(默认选中效果)的 CSS class 的链接
-
HTML5 历史模式或 hash 模式
MVVM框架采用的路由都会在地址改变的时候页面不刷新,这种应用我们称之为SPA(Single Page Application)
3.2、路由模式切换
vue-router中默认使用的是hash模式的路由,也就是前面介绍的地址栏中URL带有“#”的形式,如果需要切换成history模式,则可以在创建路由实例时进行指定,指定的配置项为mode
,可选值:
-
hash:设置路由模式为hash路由
-
history:设置路由模式为history路由
3.3、导航方式
含义:从一个组件/地址去往另一个组件/地址的方式。
在页面中,导航实现有2种方式:
-
声明式导航:通过点击链接实现的导航方式,例如HTML中的“<a>”标签,Vue中的“<router-link>”所实现的。(其性质与a标签的性质类似)
-
编程式导航:通过调用JavaScript形式API实现的导航方式,例如location.href实现的跳转效果
3.3.1、声明式导航
它就是先在页面中定义好跳转的路由规则,vueRouter中通过router-link组件来完成
<!-- 纯字符串 -->
<router-link to="/home">Home</router-link>
<!-- 动态绑定路径 -->
<router-link :to="'/home'">Home</router-link>
<!-- 对象形式 -->
<router-link :to="{ path: '/home' }">Home</router-link>
<!-- 通过路由命名并且携带隐式参数 -->
<router-link :to="{ name: 'user', params: { userId: '123' }}">User</router-link>
<!-- 对象形式带查询字符串 -->
<router-link :to="{ path: '/register', query: { plan: 'private' }}">
Register
</router-link>
<!--
to 要跳转到的路由规则 string|object
to="users"
:to="{path:'path'}"
tag="tagName" 去指定声明式导航产生的链接所使用的标签,默认是a标签
-->
3.3.2、编程式导航
简单来说,编程式导航就是通过JavaScript
来实现路由跳转
this.$router.push("/login");
this.$router.push({ path:"/login" });
this.$router.push({ path:"/login",query:{username:"jack"} });
// 不要将path属性与params属性一起使用,这样会导致params路由参数获取不到
// name属性可以与params属性传参一起使用
this.$router.push({ name:'user' , params: {id:123} });
this.$router.go( n );//n为数字 负数为回退
this.$router.back(); // 返回上一页
注意点:编程式导航在跳转到与当前地址一致的URL时会报错,但这个报错不影响功能:
如果患有强迫症,可以在路由入口文件index.js
中添加如下代码解决该问题:
// 该段代码不需要记,理解即可
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch((err) => err);
};
3.4、路由重定向
-
概念:用户在访问地址 A 的时候,强制用户跳转到地址 C ,从而展示特定的组件页面
-
实现: 通过路由规则的
redirect
属性,指定一个新的路由地址,可以很方便地设置路由的重定向
代码示例
<script type="javascript">
var router = new VueRouter({
// routes是路由规则数组
routes: [
// 每个路由规则都是个配置对象,至少有path和component两个属性(重定向除外)
// path表示当前路由规则匹配的hash地址
// component表示当前路由规则对应要展示的组件
{ path: '/', redirect: '/user' },
{ path: '/user', component: User },
{ path: '/register', component: Register }
]
})
</script>
component属性是可选属性,因此在写的时候需要注意,写错了也不会报错的。
3.5、嵌套路由
路由前缀: /admin/user/add /admin/user/del /admin/user/mod
相同部分可以提取出来,减少重复劳动。
上述概念在vue中被称之为叫做嵌套路由。
套娃,可以按照之前的nodejs处的路由前缀去理解。(当有些路由有公共部分的前缀时,在vue中就可以使用嵌套路由)
嵌套路由最关键在于理解子级路由的概念:
比如我们有一个/users
的路由,那么/users
下面还可以添加子级路由,如:/users/index
、/users/add
等等,这样的路由情形称之为嵌套路由。
核心思想:在父路由组件的模板内容中添加子路由链接和子路由填充位(占坑),同时在路由规则处为父路由配置children属性指定子路由规则:
routes: [
{
path: "/user",
component: User, //这个不能丢
// 通过children属性为/user添加子路由规则
children:[
// 子路由地址前不能写“/”,如果写了则表示从根开始
{ path: "index", component: Index },
{ path: "add", component: Add },
]
}
]
<!-- 需要在 User组件中定义一个router-view 用于嵌套路由的渲染显示 -->
<router-view></router-view>
3.6、404路由
作用:用于处理当路由匹配不上的时候页面的展示(不做404路由,则页面限时白板页面)
由于Vue路由是从上到下执行的,只要在路由配置规则中最后面放个*号(通配符)路由就可以了,例如:
const routes = [
{ path: "/hello", redirect: Hello },
{ path: "/about", component: About },
{ path: "/news", component: News },
// 404路由
{ path: "*", component: NotFound },
];
正常情况下404找不到会有状态码,是404,请问,为什么我们现在看到的状态码是200?
目前是在做前端开发,不是后端开发,无法指定返回的状态码,等到vue项目上线后可以与后端服务器结合实现状态码的指定。
3.7、路由参数
本节就是为了restful服务的,看如果在vue中使用restful形式进行参数传递。
-
如何传递
-
在声明路由的时候,将可变部分通过“
:变量名
”的形式进行替代
-
-
如何获取
-
获取this.$route来获取
-
// 传递参数id
var router = new VueRouter({
// routes是路由规则数组
routes: [
{ path: '/user/:id', component: User },
// 此处的“:”只是在声明的时候写,在使用的时候不需要写“:”
]
})
<template>
<div>
<!-- 单文件形式的组件, 可以在视图中直接接收路由参数,但是一般不这么用 -->
这是news组件{{$route.params.id}}
</div>
</template>
路由规则中的“:”只是在声明的时候写,在使用的时候不需要写“:”,例如如下代码:
问题:如上代码,如果路由规则里声明需要传递参数,但是实际使用的时候没传递参数会怎么样?
答:如果声明需要传递参数,但是实际不传的话则会影响落地页的显示,显示成白板(但是不报错)。但是如果有404路由在规则的最后,则匹配404路由。
注意:在实际开发的时候会有可能需要传参也可能不需要传参的情况,这个时候需要用到可选路由参数
点。
定义可选路由参数的方式很简单,只需要在原有的路由参数声明位置后面加上个?
即可。例如:
{ path: "showdetail/:id?", component: ShowDetail },
3.8、路由元信息
有时,我们可能希望将任意信息附加到路由上,例如在后续做登录判断的时候需要标记哪些地址必须登录后才能访问。这些事情可以通过接收属性对象的meta
属性来实现,定义路由的时候我们可以这样配置 meta
字段:
const routes = [
{
path: "/posts",
component: PostsLayout,
children: [
{
path: "new",
component: PostsNew,
// 只有经过身份验证的用户才能创建帖子
meta: { requiresAuth: true },
},
{
path: ":id",
component: PostsDetail,
// 任何人都可以阅读文章
meta: { requiresAuth: false },
},
],
},
]