文章目录
前端路由
前端路由时基于url中的哈希值进行响应跳转的一个前端浏览器技术,在h5之前,哈希值用于页面之间的锚点,但h5之后,单页面比较流行,就根据哈希值不会
传递到服务器这种特点,在页面进行跳转时,就可以不用发送网络请求;
一个完整的url 在#后面的路径所有的内容就是哈希值,设计的初衷,页面的锚点,在h5之后单页面应用比较普遍,整个项目只有一个页面,但是其他页面不显示,根据页面设置的哈希值进行页面跳转,这种采用哈希值来进行的页面跳转的技术就是前端路由
哈希值的技术是前端浏览器的技术,没次请求不会把哈希值传递给服务器在进行页面跳转的时候就可以不通过网路来显示页面
传统js使用哈希值设置前端路由;
<li><a href="#set">设置</li> 跳转指定哈希值的锚点,在前端路由中,将使用哈希值判断跳转指定的页面;
在 hashchange 事件中,会监听哈希值是否发生改变,当哈希值发生改变时,获取当前的哈希值,返回指定的页面;
vue 前端路由
在vue中 为我们内置了路由组件< router-view >标签,把哈希值对应的路由模板显示在router-view中;
< router-link to="/home" > 路由跳转组件,跳转指定哈希值页面,不用带#,一般在前面添加/ 看起来更像路径;
to 属性也可以添加一个路由跳转对象,也可以自定义跳转对象,跳转之后通过获取对应路径的跳转对象获取传递的数据;
对象第一个属性,path :指定要跳转的路径 对象的第二个属性,可以时query :指的是查询字段
< router-view></ router-view> //把哈希值对应的页面显示在router-view
var router = new VueRouter({}) //创建路由对象,在路由对象里面添加路由匹配规则;
匹配规则:
routes:[path:"/home":component:"<div></div>"] //配置路由和页面的对应关系,每个路由应该映射一个组件。 其中"component" 可以是通过 Vue.extend() 创建的组件构造器, 或者,只是一个组件配置对象。
path 对应组件的哈希值,当跳转这个哈希值,就会到指定的模板; component :哈希值对应的组件页面;
redirect:"/home" 重定向到home模板;
最后在经路由实例注入到根组件中,就创建好一个路由了; router:router;
this.$ router 和 this.$ route 区别
this.$router 路由器 可以在任何组件被访问 ;
官方文档
通过注入路由器,我们可以在任何组件内通过 this.$router 访问路由器,也可以通过 this.$route 访问当前路由
可以理解为:
this.$router 相当于一个全局的路由器对象,包含了很多属性和对象(比如 history 对象),任何页面都可以调用其 push(), replace(), go() 等方法。
this.$router.push() 想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。
也可以设置成一个对象,里面包含 path , query , params , name , 同样的规则也适用于 router-link 组件的 to 属性。
this.$router.replace() 替换当前页面的路由,不会添加进history中 , 也可以设置成一个对象,里面包含 path , query , params , name , 同样的规则也适用于 router-link 组件的 to 属性。
this.$router.go(val) 直接跳转到指定的路由;在history记录中前进或者后退val步,当val为0时刷新当前页面。
this.$router.back() 回退到下一个history记录;
this.$router.forward() 前进到下一个history记录;
this.$route 表示当前路由对象,每一个路由都会有一个 route 对象,是一个局部的对象,可以获取对应的 name, path, params, query 等属性。
所以 我们可以在组件中监听 $route 里面的数据,只要当前数据发生改变,就证明页面发生跳转或修改,在执行相应的操作;
动态路由
我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。
那么,我们可以在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果:
path: ‘/user/:id’
一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。于是,我们可以更新 User 的模板,输出当前用户的 ID:
提醒一下,当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。
不过,这也意味着组件的生命周期钩子不会再被调用。
不过我们可视使用 watch 监听 $route:function(to,from) 来监听数据的变化;
或者使用:(监听守卫)
beforeRouteUpdate 字段 beforeRouteUpdate(to,from){} 监听路由的变化;
通配符 ‘*’ 一般使用最后一位;
当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:
我们也可以将:to 传递一个对象
path: 此次跳转的路由地址;
query: 本次跳转的查询字段;
params : 动态路由的地址将传入本地址,需要传入其他参数,必须声明本name字段,并且可以省略path路径;(如果只是单传的动态地址,可以不用声明name字段);
name: 路由唯一name值,通常首字母大写,但是,动态路由路径需要设置在params中;
使用props进行传值; 解耦
在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。
使用params进行传值,并设置name 字段,在路由对象中的规则中,添加props:true; route.params 将会被设置为组件属性。也就是说我们可以使用props进行接受数据;
这样就就能减少使用$route增加耦合性;
函数模式:
你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合等等。
props:route=>({
id:'我是第'+route.id+'个',
//route 代表当前路由对象;
})
路由嵌套
一个被渲染组件同样可以包含自己的嵌套 , 就形成了路由嵌套,要在嵌套的出口中渲染组件,需要在 VueRouter 的参数中使用 children 配置:
children:[
path:'child' //不用加'/',以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径;
name:'Child' //也可以直接使用name名直接进行条转;
component:'<div>' //页面模板,也可中使用import 进行导入;
]
你会发现,children 配置就是像 routes 配置一样的路由配置数组,所以呢,你可以嵌套多层路由。
在子路由使用动态路由时,使用name字段进行条钻,不设置动态路由的动态片段,并且在params中也不设置相应的值,就会去父路由中的params中进行查找并使用;
编程式导航
在js 进行路由传值 push replace
this.$router.push({
path:"/user", //地址
query:{} 查询字段
params:{} 动态片段和全匹配片段
name:""
})
replace 声明式导航;
<router-link to="/user" replace>我是替换当前页面</router-link>
命名视图
<router-view/> 不再是单一的出口, 我们可以设置name 属性,将视图进行区分, 将模板渲染到指定的视图中;
在路由对象中 component 字段 此时变成了components 值为一个对象,包含所有需要渲染到视图中的键值对, name:component
在不添加name属性,默认name:default;
重定向和别名
我们可以在当前路由对象 添加这样一个规则,
redirect:"/user" 将当前路由重定向到"/user" 中;
也可以使用
redirect:{
name:‘User’
}
甚至可以是一个方法
redirect:to=>{
to //当前路由
// return 重定向的 字符串路径/路径对象
}
而别名则是 /a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样。
使用 alias: ‘/b’ 进行设置别名
就相当于,一个页面拥有两个路由匹配,匹配到/a,或者/b 都会显示/a里面的内容;
导航守卫
正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的
导航守卫就是路由发生时跳转时的一些钩子函数,说直白点,路由跳转是个大过程,有细分了很多小过程,这些小过程对应了相应的钩子函数,在相应的钩子函数做相应的事,就是导航守卫,
导航守卫的功能:在路由守卫可以停止路由跳转,一般也称为路由拦截,可以实现一些登录判断。
三种类型的导航守卫 1全局导航守卫 2 路由内导航守卫 3组件内的导航守卫
三种类型守卫
在路由实例直接定义了导航守卫,特点是全局所有的路由导航都会被触发这些钩子函数,
全局前置守卫
在路由跳转前触发,在没有组件内没有beforeRouterLeave这个钩子函数时,先触发这个钩子函数,大多数在这个钩子函数种写登陆验证,是否进入相应的路由跳转
router.beforeEach((to,from,next)=>{})
钩子函数接受的三个参数
to 即将跳转的目标路由对象
from 当前导航正要离开的路由对象
next() 进行管道中的下一个钩子函数,如果钩子函数全部执行完毕,此时导航的状态就有待定变成确认,(请务必执行这个函数,如果不执行,则不会进入下一个钩子函数)
next(false) 中断当前的导航,结束跳转,此时url 会重置到当前正要离开的路由;
next("/") | next({path:"/"}) //改变当前路由的跳远源路径,跳转到你设置的地址,
你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: ‘home’ 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项
next(error) 将错误抛出并中断当前的导航,有router.onError() 进行处理;
全局解析守卫
在导航确认前,同时在异步路由解析完毕之后和组件内导航守卫执行后调用
router.beforeResolve((to,from,next)=>{})
全局后置钩子
在导航确认后执行改钩子 没有next()函数;,执行完后置钩子,导航确定状态,组件的dom也会重新更新,
router.afterEach((to,form)=>{})
路由内独享守卫
在路由规则对象种定以的守卫,在全局前置守卫之后触发改钩子函数; 在组件模板解析之前执行改钩子函数;
beforeEnter:(to,from,next)=>{} //注意格式 使用匿名函数
组件内的导航守卫
在路由独享守卫之后执行改钩子函数,发生在组件没有创建之前,所以此时this不能使用,如果需要使用,也可以在next((vm)=>{}) 中使用组件对象
不过使用vm时 导航被确认的时候执行回调 发生在afterEach之后 ,并且组件的已经成功渲染完毕之后; 并且把组件实例作为回调方法的参数。
beforeRouteEnter 是唯一一个拥有该回调函数的守卫,因为其他守卫已经可以使用this了;
beforeRouteEnter(to,from,next){}
当动态路由发生改变并且组件被复用的时候调用该钩子函数,组件复用,就是组件没有经历销毁和创建,而是存储在内存中,等下次使用的时候在从内存中取出,
不会经历创建声明周期这些钩子函数; 那些导航会经历组件复用呢,动态路由的跳转就会经历组件复用;或者查询字段发生改变,组件也是会复用
都会触发该钩子函数;
beforeRouteUpdate(to,from,next){}
当路由发生导航的时候触发,通常用于用户修改一些数据没有保存的时候,可以通过next(false) 进行阻止;
beforeRouteLeave(to,from,next){}
梳理下导航守卫执行流程
官网上
导航被触发。
在失活的组件里调用 beforeRouteLeave 守卫。
调用全局的 beforeEach 守卫。
在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
在路由配置里调用 beforeEnter。
解析异步路由组件。
在被激活的组件里调用 beforeRouteEnter。
调用全局的 beforeResolve 守卫 (2.5+)。
导航被确认。
调用全局的 afterEach 钩子。
触发 DOM 更新。
调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
理解
当导航被触发时,首先执行组件内的离开守卫(beforeRouteLeave),通常在这个守卫询问是否离开本页面,也可以通过next(false)进行阻止导航,
然后执行全局前置守卫 beforeEach,在这个守卫里面,经常用于判断用户是否登陆,
当组件被复用时 此时会触发 组件内的beforeRouteUpdate()守卫 此时执行的是当前导航正要离开的路由对象的组件内守卫,
如果没有复用组件 就会继续往下执行
然后执行路由独享守卫,beforeEvent
解析异步路由组件。
然后执行导航目标对象组件内的进入守卫beforeRouteEnter,
调用全局解析守卫beforeReslove
导航被确定状态,本次跳转结束,
触发全局后置钩子函数afterEach
创建组件 进入组件声明周期函数的创建阶段并渲染dom
然后 组件进入守卫如果使用了next回调,在渲染完dom之后 将组件实例传递到beforeRouteEnter的next函数中;
路由元信息
定义路由的时候可以配置 meta 字段:
里面存放这一些数据,我们获取当前存放的数据使用 $route.meta 获取当前路由对象中的字段,
如果想要会去二级 或者多级路由的meta 的meta字段 则使用 $route.matched 获取一个下面所有二级或者多级
的meta字段数据的数组,使用some筛选数据进行判断是否登陆成功;
虚拟dom
虚拟DOM:vue底层实现数据更新和数据渲染的一项技术,通过js对象模拟DOM节点,所形成js对象就是虚拟DOM
1 先把渲染的数据渲染上
2 根据真实DOM生成虚拟DOM的结构
3点击按钮让数据进行更新
4 更新数据之后,形成一个新的虚拟DOM,也就是更新之后的虚拟DOM
5 实现局部更新,把更新前的虚拟DOM和更新后的虚拟DOM进行对比,通过diff算法,找不不同之处,实现局部更新
异步懒加载路由
详情
omponent: ()=>import("@/components/pages/signIn/signIn"),