Vue—09—路由vue-router;
动态路由:
多个路由指向同一个组件;比如/user/:id,id传的不一样,但是会都匹配这个路由记录,然后指向同一个组件;
注意两点(1)这个时候组件是会被复用的,组件实例并不会销毁重建,而是直接使用;(2)组建内部可以通过this.$route.params来获取后面跟的参数
嵌套路由
一个组件内部还有route-view,即嵌套了一个路由视图;如何访问,在路由表里定义children数组;
命名路由
在路由表里,除了用path属性表示匹配到的组件外,也可以用name属性;
编程式路由导航
除了在router-link组件中导航外,还可以使用this.$route.push(),这种方式是在js里写的,所以叫编程式;
const userId = '123' // 1.参数可以是字符串 router.push('home') // 2.参数也可以是对象 router.push({ path: 'home' }) // 2.1参数是一个对象,对象里面使用name表示命名路由,适用params表示动态参数 router.push({ name: 'user', params: { userId: '123' }})。 // -> /user/123 //等同于这样写:router.push({ path: `/user/${userId}` }) // -> /user/123 // 2.2参数是一个对象,对象里面使用path表示路由跳转路径,使用query属性表示查询参数; router.push({ path: 'user', query: { userId: '123' }})。// ->user?userId=123 // 3.注意: //如果对象里提供了path属性,params 属性会被忽略,但是query属性不会忽略; //这里的 params 不生效. //如果想要params生效,请配合name使用;
router.push({ path: '/user', params: { userId }}) // -> /user
参数解藕(路由组件穿参)
如果组件里一直通过this.$route.params或者this.$route.query的方式取值,那么这个组建会和路由耦合性太高,如果这个组件平时随便用用自然无所谓,可如果是想要它做一个高度可复用的组件,那最好是进行参数解藕,把this.$route.params当作props参数传递过来;
路由视图:
router-view就是路由视图;
路由记录:
routes路由表
配置中的每个路由对象为 路由记录
一个路由匹配到的所有路由记录会暴露为 $route
对象的 $route.matched
数组;
路由守卫
全局守卫
- beforeEach,
- resolveEach
- afterEach
路由表守卫
- beforeEnter
组件守卫:
- beforeRouteEnter
- beforeRouteUpdate
- beforeRouteLeave
路由元信息
通过路由记录获取在路由表上定义的meta信息;
this.$route.matched.forEach( e => e.meta);
路由过度动画
给路由视图加上一个<transition></transition>组件即可;
路由懒加载
无webpack: routes: [{ path: '/foo', component: ()=>{Promise.Resolve({组件对象})} }] 有webpack: routes: [{ path: '/foo', component: ()=>{import( '路径名举例:./Foo.vue')} }]
数据获取
导航完成后在creted钩子函数里;
滚动行为
当创建一个 Router 实例,你可以提供一个 scrollBehavior
方法:
const router = new VueRouter({ routes: [...], scrollBehavior (to, from, savedPosition) { // return 期望滚动到哪个的位置 } })
导航故障
一、前后端渲染和前后端路由
后端渲染:后端已经把数据嵌套在html和css上了,然后后端给前端发送的是一个完整的html页面,浏览器显示出来就行了。
前端渲染:前端先去静态资源服务器下载html、css、js代码,并展示出来,但展示了htmlcss后,当遇到了js代码时,js代码会向后端发送请求并接受后端发送来的数据,然后进行处理(比如说js代码要循环生成x个input框,后端告诉前端x等于10,然后html就要继续多生成10个input标签), 最终得出一个完整的html,这就是前端渲染;
后端路由:
浏览器请求的每一个url,后端路由都根据路由表发送到专门的controller中进行处理(路由表应该是tomcat+spingMVC的DispacharServlet进行处理的)
前端路由:
前端路由首先是到了sqa阶段,由于我们只有一个index页面,我们想展示不同的页面,就需要调用不同的子组件模板去覆盖,哪如何根据不同的url去找不同的子组件模板?使用vue-router;
二、前端发展的几个阶段
前端的几个阶段:
1.jsp阶段或者template阶段:
需要写html代码在jsp中,由于jsp还有java代码调用数据,所以整个页面非常不清晰;
或者template阶段,html代码虽然不和java代码在一起写了,但是仍然是后端渲染,将html页面渲染好之后发送给前端;
这个个时候没有前端路由只有后端路由去根据url找controller;并且是后端渲染;
2.前后端分离阶段:
浏览器根据不同的url去静态资源服务器(可能是node服务器)请求到不同的一套html、css、js代码,将jtml、css渲染好之后,当遇到了js代码时,js代码会向后端发送请求并接受后端发送来的数据,然后进行处理(比如说js代码要循环生成x个input框,后端告诉前端x等于10,然后html就要继续多生成10个input标签), 最终得出一个完整的html,这就是前端渲染。
虽然,前后端分离阶段没有用到前端路由,但是开始前端渲染;
3.spa阶段:
这个时候,整个静态资源服务器只有一套html、css、js代码,前端服务器需要根据不同的url代码去寻找不同的子组件模板来代替index.html页面,这个时候就是前端路由;
当然遇到了js代码,也需要从后端获取数据,然后前端渲染;
https://www.bilibili.com/video/BV15741177Eh?p=101&spm_id_from=pageDr
三、路由的几种模式
路由的几种模式:
1.hash模式
2.history模式
histroty.back() 相当于 history.go(-1)
histroty.forward() 相当于histroty(1)
四、路由vue-router的简单使用
1.使用
首先配置vuerouter:
1.npm install vue-router -S
2.配置router文件下的index.js文件
3.配置main.js
其次使用vue-router:
1.在app.vue里配置《router-link》和《router-view》
2.router-link的4个属性:
3.组件如何通过vue-router切换?
《router-view》标签会展示我们替换的组件;
vue-router安装好之后,会往所有的组件里都有$router属性;
不用router-link,使用this.$router.push()进行组件的切换;
五、路由vue-router的高级使用
$router和$route的区别:
$router表示我们在index.js文件中new的router对象;
$route表示那个路由路径活跃,我们就去取哪个对象;$route的params属性就可以取到使用本路由的url的后缀;
1.动态路由(参考4传递参数,有异曲同工之妙)
即在index。js文件中设置一个动态的路由,格式为:
{ path:'/user/:suibian', component:User, },
我们在app.vue的tempalte模板的《router-link》标签的to属性中,给:suibain穿什么值,它就接受什么值,比如说suibian=aaa,
那么这个路由就会跳到User.vue组件,但是路由url变成了/usr/aaa;
然后我们在User.vue中可以通过$route.params.suibian获取到suibian的值的aaa;
2.懒加载
用到时再加载
懒加载的使用方式:
3.嵌套路由
就是子路由;
在indexjs文件中设置子路由,然后在本vue中再设置《route-link》《router-view》标签,因为子路由所展示的vue页面是覆盖本vue的;
4.传递参数
第一方式是使用动态路由的方式,在index.js文件中的router属性里写变量,
{ path:'/user/:suibian', component:User, }
然后后面的vue文件通过$route.params.变量名取值;
第二种方式是传过去一个对象,对象里有Path,这个属性是跳转的url,query是要传递的参数;
然后后面的vue文件通过$route.query.变量名取值;
这样看来还是用query的方式好一点。
注意:
所有的组件都继承自vue的原型;
vue的原型是绑定了¥router和¥route,所以¥router和¥route是所有组件都可以用的;
5.全局导航守卫(路由守卫)
所有的组件都有生命周期函数:
created():组件一被创建时调用
mounted():组件被挂载时调用
updated():组件被更新时调用;
通过这三个生命周期函数,我们可以实现进入某.vue文件时、。vue文件加载完成时、。vue文件数据发生改变时我们可以监听到并根据自己需要改变;
但是如果每一个。vue文件都写着三个函数有点太复杂了,我们可以使用全局导航守卫。
这是所有的路由都可以用的守卫;除了全局导航守卫,还有
- 路由独有导航守卫(具体去官网学习)
- 组件内守卫(具体去官网学习)
如何使用呢?我们以修改页面的title为例,第一我们先给每个路由定义一个mete属性,并写上进入我这个路由后浏览器的title要修改成的值,然后在index。js问文件中使用router调用beforeEach()方法,并调用函数
import Vue from 'vue' import VueRouter from 'vue-router' //统一管理组件的懒加载 const HelloWorld = () => import('@/components/HelloWorld.vue'); //1.加载vuerouter Vue.use(VueRouter) //2.定义路由引射表 const route = [ { path:'/helloworld', component:HelloWorld, meta:{ title:'你好世界', }, children:[ { path:'/', redirect:'hw222', }, { path:'hw111', component:HelloWorld111, }, { path:'hw222', component:HelloWorld222, }, ], }, { path:'/test', component:Test, }, ]; //3.初始化路由 const vueRouter = new VueRouter({ routes:route, mode:'history', })
//3.1添加路由守卫 vueRouter.beforeEach((to,from,next) => { window.document.title = to.matched[0].meta.title; next() }) //4.导出路由 export default vueRouter;
meta:元数据:描述数据的数据
metacalss:元类,由元类创造类,再由类创造实例;
除了由路由守卫beforeEach还有路由钩子afterEach,这些都和路由独有守卫、组件守卫一样自己去官网看吧。