- Vue路由
- 一、spa
- 什么是spa
- spa的特点
- 二、 如何实现单页面效果
- 区分router
- router的模式
- 三、 从安装创建入手
- HashHistory
- HTML5History
- 两种模式比较
- 四、 路由的使用
- 路由跳转传参
- 路由的显示容器
- 如何获取路由参数
- 五、 路由的钩子函数
- 全局前置守卫、全局解析守卫、全局后置守卫
- 路由的独享守卫
- 组件内的守卫
- Vue-router的使用方式
- 一、spa
什么是SPA
单页Web应用(single page web application,SPA),就是只有一张Web页面的应用,
是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。
- SPA的特点
- 优点:
- 1、用户操作体验好,用户不用刷新页面,整个交互过程都是通过Ajax来操作。
- 2、适合前后端分离开发,服务端提供http接口,前端请求http接口获取数据,使用JS进行客户端渲染。
- 缺点:
* 1、首页加载慢
单页面应用会将js、 css打包成一个文件,在加载页面显示的时候加载打包文件,如果打包文件较大或者网速慢则用户体验不好,首屏时需要请求一次html,同时还要发送一次js请求,两次请求回来了,首屏才会展示出来。相对于多页应用
* 2、SEO不友好
SEO效果差,因为搜索引擎只认识html里的内容,不认识js的内容,而单页应用的内容都是靠js渲染生成出来的,搜索引擎不识别这部分内容,也就不会给一个好的排名,会导致单页应用做出来的网页在百度和谷歌上的排名差。使用单页面应用将大大减少搜索引擎对网站的收录。
- 优点:
为什么页面切换快?
页面每次切换跳转时,并不需要做html文件的请求,这样就节约了很多http发送时延,我们在切换页面的时候速度很快。
有这些缺点,为什么还要使用Vue呢?
Vue还提供了一些其它的技术来解决这些缺点,比如说服务器端渲染技术(我是SSR),通过这些技术可以完美解决这些缺点,解决完这些问题,实际上单页面应用对于前端来说是非常完美的页面开发解决方案。
如何实现单页面效果 => Router
路由需要满足的功能
从用户的角度看,前端路由主要实现了两个功能(使用ajax更新页面状态的情况下):
记录当前页面的状态(保存或分享当前页的url,再次打开该url时,网页还是保存(分享)时的状态)
可以使用浏览器的前进后退功能(如点击后退按钮,可以使页面回到使用ajax更新页面之前的状态,url也回到之前的状态)
要实现这两个功能,我们需要做到:
改变url且不让浏览器向服务器发出请求
监测 url 的变化
截获 url 地址,并解析出需要的信息来匹配路由规则。
区分Router 、Route
Router: 路由器,负责路由的调度、中转
Route: 路由,用于资源通信的载体、类似于路由器上的LAN
路由的模式
• Hash
• 利用URL中的# 资源定位符
• History
• H5新增的pushState、repalceState 方法
//2
单页面应用
1,用户体验好
2,适合前后端分离
缺点:首页加载慢,
不利于seo
路由就是改变应用的路徑
路由有三种模式
history 默认‘/’ 需要浏览器支持—>html5的api运用的事HTML5的API,pushState()和replaceState()对浏览器历史记录栈修改
hash 默认’/#/'兼容性好,window.addEventListen hash change 监听地址栏
#符号本身以及它后面的字符称之为hash,可通过window.location.hash属性读取。它具有如下特点
• hash虽然出现在URL中,但不会被包括在HTTP请求中。它是用来指导浏览器动作的,对服务器端完全无用,因此,改变hash不会重新加载页面
• 可以为hash的改变添加监听事件 window.addEventListener(“hashchange”, funcRef, false)
• 每一次改变hash(window.location.hash),都会在浏览器的访问历史中增加一个记录
利用hash的以上特点,就可以来实现前端路由“更新视图但不重新请求页面”
abstract----->服务端 array方式模拟的进栈出栈的方式
添加链接描述
Vue路由$router和$route是什么?区别是什么?
$router为VueRouter的实例,相当于一个全局的路由器对象,里面含有所有的子对象和属性,例如history对象。。。经常用的跳转链接就可以用this.$router.push,和router-link跳转一样。
以history对象来举例:
$router.push({path:‘home’}),本质是向history栈中添加一个路由,在我们看来是切换路由,但本质是
this.$router.push会往history栈中添加一个新的history记录。
$router.replace({path:‘home’}),//替换路由,没有历史记录【常用于404页面】
详细见vue官方文档
返回上一个历史history用$router.go(-1)
$route是正在跳转的这个路由的局部对象[路由对象,信息对象],里面可以获取当前路由的name,path,query,parmas,hash,fullpath,meta等 可以拿里边的值来做各种判断。
$route.path 字符串,等于当前路由对象的路径,会被解析为绝对路径,如/home/ews
$route.params 对象,含路有种的动态片段和全匹配片段的键值对,不会拼接到路由的url后面
$route.query 对象,包含路由中查询参数的键值对。会拼接到路由url后面
$route.router 路由规则所属的路由器
$route.matchd 数组,包含当前匹配的路径中所包含的所有片段所对象的配置参数对象
$route.name 当前路由的名字,如果没有使用具体路径,则名字为空
vue-router传递参数分两大类
-
1,编程式的导航 router.push
-
2,声明式的导航<router-link>
-
vue-router传递参数分两大类
1, 编程式的导航 router.push传递参数类型一字符串:字符串的方式是直接将路由地址以字符串的方式来跳转,这种方式很简单但是不能传递参数:
this.$router.push("home");
传递参数类型二对象:传递参数主要就是以对象的方式来写,分为两种方式:
1; 命名路由[params]、 2;查询参数[query]。
命名路由的前提就是在注册路由的地方需要给路由命名如:
命名路由传递参数需要使用params来传递,这里一定要注意使用params不是query。
目标 页面接收传递参数时使用params
特别注意:命名路由这种方式传递的参数,如果在目标页面刷新是会出错的。查询参数其实就是在路由地址后面带上参数。
和传统的url参数一致的,传递参数使用query而且必须配合path来传递参数而不能用name
目标页面接收传递的参数使用query。this.$route.query.userId
注意:和name配对的是params,和path配对的是query- 2,声明式的导航
声明式的导航也分为两种方式:例子如下:
1; 命名路由[params]、 2;查询参数[query]。字符串
<router-link to="news"> click to news page </router-link>
命名路由
<router-link :to="{ name: 'news', params: { userId: 123}}"> click to news page </router-link>
查询参数
<router-link :to="{ path: '/news', query: { userId: 123}}"> click to news page </router-link>
总结:路由传递参数和传统传递参数是一样的,命名路由类似表单提交而查询就是url传递,在vue项目中基本上掌握了这两种传递参数就能应付大部分应用了,最后总结为以下:
- 1.命名路由搭配params,刷新页面参数会丢失
- 2.查询参数搭配query,刷新页面数据不会丢失
- query使用path和name传参跳转都可以,而params只能使用name传参跳转。
- 3.接受参数使用this.$router后面就是搭配路由的名称就能获取到参数的值
3,动态传参
现有如下场景,点击父组件的li元素跳转到子组件中,并携带参数,便于子组件获取数据。
goDescribe(id){
this.$router.push({
path: `/describe/${id}`,
})
}
需要对应路由配置如下:
{
path: '/describe/:id',
name: 'Describe',
component:line
}
很显然,需要在path中添加/:id来对应 $router.push 中path携带的参数。在子组件中可以使用来获取传递的参数值。
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用离开守卫。
- 调用全局的 beforeEach 守卫。
- 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
- 在路由配置里调用 beforeEnter。
- 解析异步路由组件。
- 在被激活的组件里调用 beforeRouteEnter。
- 调用全局的 beforeResolve 守卫 (2.5+)。
- 导航被确认。
- 调用全局的 afterEach 钩子。
- 触发 DOM 更新。
- 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。
注:“导航”表示路由正在发生改变。
作用:主要用来通过跳转或取消的方式守卫导航。
植入方式:全局的, 单个路由独享的, 或者组件级的。
全局前置守卫:
router.beforeEach
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
当一个导航触发时,全局前置守卫按照创建顺序调用。
守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。
每个守卫方法接收三个参数:
- to: Route: 即将要进入的目标 路由对象
- from: Route: 当前导航正要离开的路由
- next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
- next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
- next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
- next(’/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: ‘home’ 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。
- next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
确保要调用 next 方法,否则钩子就不会被 resolved。
全局解析守卫
在 2.5.0+ 你可以用 router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,
区别是:在导航被确认之前,
同时在所有组件内守卫和异步路由组件被解析之后,
解析守卫就被调用。
全局后置钩子
你也可以注册全局后置钩子,然而和守卫不同的是,
这些钩子不会接受 next 函数也不会改变导航本身:
router.afterEach((to, from) => {
// ...
})
路由独享的守卫
你可以在路由配置上直接定义 beforeEnter 守卫:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
这些守卫与全局前置守卫的方法参数是一样的。
组件内的守卫
最后,你可以在路由组件内直接定义以下路由导航守卫:
-
beforeRouteEnter
-
beforeRouteUpdate (2.2 新增)
-
beforeRouteLeave
const Foo = {
template:...
,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例this
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例this
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例this
}
}
beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
不过,你可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
})
}
注意 beforeRouteEnter 是支持给 next 传递回调的唯一守卫。对于 beforeRouteUpdate 和 beforeRouteLeave 来说,this 已经可用了,所以不支持传递回调,因为没有必要了。
beforeRouteUpdate (to, from, next) {
// just use `this`
this.name = to.params.name
next()
}
这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。
beforeRouteLeave (to, from , next) {
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if (answer) {
next()
} else {
next(false)
}
}