Vue-Router 基础入门教程
前言
这周的计划是用VUE将之前的小demo的前端给重构了,并且做成前后端分离的样式,因为之前的那个聊天室的demo几乎都是在一个路由上完成的,所以学习Vue-router是不可避免的,本次笔记是我在学习vue-router这个框架过程中的一些笔记。中间也穿插了部分知识点,希望能帮助到正在学习Vue-router的朋友。
什么是vue-router?
注意:这里的路由并不是指我们平时所说的硬件路由器,这里的路由就是SPA(单页应用)的路径管理器。再通俗的说,vue-router就是WebApp的链接路径管理系统。比如你点一个连接,vue-router会帮你匹配到相关的视图,并且返回给你。
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。简直不要太爽。最后一句是我自己加的。
既然官网说了,VUE主要构建单页应用,那什么是单页应用,SPA。
注意:这里的SPA 不是各种会所的那种SPA,而是SPA(single page application),单一页面程序,怎么理解单一页面程序,就是整个应用编译之后就只有一个index.html文件,和我们之前做的那些写一堆html,css思路截然不同,单页面应用的思路是一个index.html里面有一个容器,在用户进行交互的时候,并不会重新加载某个界面,而是只选择把某个视图更新到容器中去显示。比如当你点开首页的时候,vue-router就把首页相关的内容放到容器去显示,需要登录的时候就把登录界面相关的样式,按钮放到容器里去展示。
正因为VUE是单页面应用,所以你的标签是不起作用的,就一个html,你跳转能跳转到哪去?所以我们才需要vue-router去管理我们的路由调度。
vue-router 路由模式
vue-router默认提供了两种路由模式,history
和 hash
模式。
hash 模式
vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载,这样的好处是无需我们在服务端做任何配置就可以无缝接入我们的后端。# 是 url 的一个锚点,记载了网页中的位置,在实际的请求中,hash并不会被带到后端。所以说Hash模式通过锚点值的改变,根据不同的值,渲染指定DOM位置的不同数据。hash 模式的原理是 onhashchange 事件(监测hash值变化),可以在 window 对象上监听这个事件。
history模式
由于hash模式本身会在我们的url中带一串hash
,而且还有 #
符号,所以我们的URL可能会有那么一丢丢不好看,这个我觉得感知不强
。如果你想要比如 user/id/1
这种比较优雅的模式,那么可以使用history模式,不过这种模式尽管带来了比较优雅的url,但是需要我们单独设置服务端,比如Nginx,我们可能要加这样一行配置,才可以保证我们的VUE项目可以正常运行:
location / {
try_files $uri $uri/ /index.html;
}
复制代码
更加具体的部署教程,等到我部署的时候会另做笔记。
安装
和vue一样,vue-router 本身也提供了两种安装方式供我们选择。
CDN方式
我们可以直接引入vue-router.js这个文件使用vue-router:
<script src="/path/to/vue.js"></script>
<script src="/path/to/vue-router.js"></script>
NPM方式
第二种方式则是在我们VUE项目中集成:
npm install vue-router
之后在main.js中引入我们的vue-router:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
new Vue({
router,
render: h => h(App)
}).$mount('#app')
为了更加规范的去使用vue-router,后面的内容我们从官方为我们配置好的目录去做,首先我们新建一个vue 项目,记得选择自定义安装,然后把vue-router这个选项打钩。
之后会让你选择是否启用histoty模式,本案例中选择的是。
然后就静静等吧,一分钟过去了,两分钟过去了,好慢,时间静静的流入指尖,一瞬间好像堕入虚无,看着控制台界面闪动的字符,点上一支香烟,非常上流的感慨道,这可真他娘的慢啊。
打开我们新建的项目,你会发现vue脚手架已经帮我们把router默认配置好了,最明显的区别就是多了一个router文件夹,里面有一个index.js的文件,我们的路由主要在这个文件配置。
目录大概长这个样子:
我们点开index.js,这里面有目前已经配置完成的路由信息:
// 这块就是配置我们的路由信息了,一个是首页 home,一个是关于页面 about
// 其中 name: 'Home' 是我们的别名, path: '/',是我们的路由路径,component是我们路由对应的组件。
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue') // 官方默认的除了Home其他视图组件都这样导入,所以后续我们也是采取这样的方式。
}
]
// mode 说明了我们使用的是history模式,如果不设置mode,则会使用默认的hash模式。
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
点开App.vue,我们一探究竟。
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view/>
</div>
</template>
其中可以理解为我们上文中说谈到的容器,用来显示我们的视图内容。 Home 类似于html中的 "a" 标签,起到一个页面之间跳转的作业。
页面跳转
页面跳转呢,vue-router 除了直接修改地址栏网址,主要提供了两种方式,声明式
和 编程式
。
声明式
声明式就是 Home 这种形式,直接用标签的方式声明我就是一个跳转的标签。当然,这种方式是最简单的写法,俗称乞丐版跳转。
当然,如果页面之前需要传递参数,我们只需要用进阶版的写法就可以了:
<router-link :to="{name:xxx,params:{key:value}}">valueString</router-link>
其中,name 是我们跳转的url的别名,比如Home,About,params则是我们要携带过去的参数,其中key 和 value 可以有多个,也就是说我们可以携带多个参数过去。
参数带是带过去了,我那边怎么收呢?同样也很简单:
$route.params.key
除了这一种之外,vue还支持直接使用url 进行传值,比如 user/id id 就是传过去的值。使用这种方式我们需要在index.js 去设置我们的路由,这点和django非常像,都是在参数之前加个 冒号。
{
path:'/user/:id/',
// 其他属性省略掉了
}
之后我们就可以直接使用url传值了,不过我还是比较习惯使用前一种。因为参数如果内容太长的话,url会非常难看。
<router-link to="/user/1">params</router-link>
同样的,我们还可以通过name匹配路由,使用query来传递参数。
<router-link :to="{ name:'xxx',query: { key:value}}" >
router-link跳转Query
</router-link>
这个我们是不需要修改index.js的,只要之前配置了路由,直接name属性就可以匹配到,只有url传递参数这一种需要我们修改我们之前设置好的路由。
获取参数,注意这个this。
this.$route.query.queryId
知识点,param 和 query 的区别:
主要有两个:
- 使用params传参只能用name来引入路由,即push里面只能是name:'xxx',不能是path:'/xxx',因为params只能用name来引入路由,如果这里写成了path,接收参数页面会是undefined。query name 和 path 都支持。
- query 更类似于get请求,url会加上参数信息,而param类似于post请求,url并不会携带参数信息。
编程式
编程式 相对于声明式就简单的多了,直接一句搞定:
parm的方式
// 不带参数
this.$router.push({name:'xxx'})
// 带参数
this.$router.push({name:'xxx',params:{key:value}})
query 的方式:
this.$router.push({name:'xxx',query:{key:value}})
因为是编程式路由,所以我们能玩的姿势就比较多,其他骚操作:
this.$router.go(-1)//跳转到上一次浏览的页面
this.$router.replace('/menu')//指定跳转的地址
this.$router.replace({name:'menuLink'})//指定跳转路由的名字下
很多人一看,你这咋replace也能跳转,不是有push了?
知识点:push 和 replace 的区别:
- 使用push方法的跳转会向 history 栈添加一个新的记录,当我们点击浏览器的返回按钮时可以看到之前的页面。也就是说是支持后退的。
- 使用replace方法不会向 history 添加新记录,而是替换掉当前的 history 记录,即当replace跳转到的网页后,'后退' 按钮不能查看之前的页面。
高级技巧:
这个的话,暂时其他的我还没有用的特别多,关于高级技巧vue-router 官方文档给了非常详细的说明,这里呢,我主要想讲一下导航守卫:
导航守卫:
导航守卫的应用场景非常明确,类似于Django中的中间件,以及Spring 中的拦截器,都是在请求执行之前的一个环节,或者说做一个权限校验,合法的请求我们就放行,不合法的请求我们就重定向,或者在每个请求执行之前,做额外的一些工作,比如添加响应头,等等等等。
全局前置守卫:
这个顾名思义,就是在每个导航执行前执行。 具体的写法如下,在index.js文件中添加:
router.beforeEach((to, from, next) => {
let token = localStorage.getItem('Authorization')
if(to.name == "Login" || to.name == "Reigster"){
next()
}
else{
if(token == null){
next('/login')
}else{
next()
}
}
})
我这里的逻辑其实就是判断本地token是否存在,如果不存在的话就重定向到登录界面。
这边的话知识点主要有两个:
参数
- to 即将要进入的目标 路由对象
- from 当前导航正要离开的路由
- next 要执行的操作
第二个:
- next() 什么也不执行,放行。
- next(false) 中断当前导航,
- next('/') 或者 next({ path: '/' }) 跳转到一个不同的地址。
- next(error 则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
全局后置守卫:
router.afterEach((to, from) => {
// ...
})
路由独享的守卫:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})