时间:2022-03-25 09:40:32 | 栏目:vue | 点击:次
后端路由:
URL 的请求地址与服务器上的资源对应,根据不同的请求地址返回不同的资源。
前端路由:
在单页面应用中,根据用户触发的事件,改变URL在不刷新页面的前提下,改变显示内容。
URL 的 hash 模式
改变 hash
值的时候,#是一个位置标识符,可以进行页面内的位置跳转,并不会刷新页面。
通过 location.hash
改变页面的 hash 值,如:
我们发现页面并不会刷新。
URL
的 history
模式
history
模式,有 5 种改变 url 而不刷新页面的方法,分别为:
history.pushState()
//压入栈history.replaceState()
// 替换当前url,不能返回上一个页面history.back()
//返回上一个页面history.go(n)
//n的值可以是大于0的,表示向前几个,小于0时,表示向后退几个history.forward()
//向前一步history.go(-1)
等价于 history.back()
history.go(1)
等价于 history.forward()
前端三大框架,都有自己的路由:
Angular
有 ngRouter
React
有 ReactRouter
Vue
有 vue-Router
npm install vue-router --save
使用 vue-router
的前提是 vue 必须使用
在 router 文件夹内 index.js 引入vue-router
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) //引用 vue-router 插件
//配置路由与组件之间的关系 const route=[ { path: '/', // 当访问 '/'的时候 路由重定向 到新的地址 '/home' redirect: '/home', }, { path: '/home', component: home, }, { path: '/login', component: login, }, ]
const router = new VueRouter({ mode: "history", //设置模式 routes });
到 main.js
中,vue 实例化中,把 router
挂载的 vue 上。
let app = new Vue({ el:'#app', data:{}, // 挂载到vue上面 router, })
<!-- 添加路由 --> <router-link to="/home">首页</router-link> <router-link to="/about">关于</router-link> <!-- 展示路由内容 --> <router-view />
router-link
默认会被渲染成 a 标签,如:
<router-link to="/home">首页</router-link> // 渲染成 <a href="#/home" rel="external nofollow" >首页</a>
router-view
是用来占位的,将路由对应的组件展示到该位置。
路由模式有两种:hash
和 history
模式。
vue-router
默认使用的是 hash 模式。
hash
的 url 中锚点就是 #xx 号后的内容,通过锚点作为路由地址,我们通常改变的是#号后的内容,实现浏览器渲染指定的组件,锚点发生改变会触发 onhashchange
事件。
history
就是正常的 url,没有#号,使用的时候需要服务器进行配置。history模式下,对应的方法与上述 5 个方法是一样的。
vue-router
中可以指定需要的模式:
const router = new VueRouter({ mode:'history' })
router-link
默认会渲染成 a 标签,但是有时候你想渲染成别的标签也是可以的。
tag属性是用来设置 router-link 标签渲染类型的,如我们想把 router-link
渲染成 button
,如:
<router-link to="/home" tag="button">首页</router-link>
查看渲染后的元素,发现变成 button
标签了,对应的 to 添加的属性值就会失效。此时点击无法跳转到对应内容,可继续阅读下边跳转方式。
除了 button
,tag 的属性值还可以是其他任意标签,router-link 自动渲染成对应的标签。
replace与上边 history
模式中的 replaceState
对应,跳转的时候不会留下 history
记录,指定replace
的情况下,不能返回上一页。
<router-link to="/home" replace>首页</router-link>
active-class
设置 router-link
点击当前选中的类名,默认情况下类名为:router-link-active
<a href="#/" rel="external nofollow" aria-current="page" class="router-link-exact-active router-link-active"> 首页 </a>
设置当前元素样式需要设置到:router-link-active。
设置 active-class ,如:
<router-link to="/" active-class="active">首页</router-link> // router-link-active 类名会被替换成 active
如果需要把全局的 router-link
的选择类名都修改成自定义的,一个一个单独设置工作量太大,可以在 router 中统一设置。
const router=new VueRouter({ routes, mode: 'hash', linkActiveClasss: 'active' //统一设置类名 })
// 简单写法 <router-link to="/">首页</router-link> //使用动态的path <router-link :to="{ path : '/' }"></router-link> 可以使用path 也可以使用name //带传参跳转1 <router-link :to=" { name:'home', params:{ id:'123' , name:'gq' }} "> </router-link> //带传参跳转 <router-link :to=" { path:'/', query:{ id:'123' , name:'gq' }} "> </router-link>
// 简单写法 this.$router.push({ path:'/' }) // push 与history.pushState 一样 //带参跳转 this.$router.push({ name: 'home' , params: { id:'123' , name:'gq' } }) //带多种参数 this.$router.push({ name: 'home' , params: { id:'123' , name:'gq' }, query: { plan:'private' } })
在某些情况下,一个页面的 path
路径可能是不确定的,如:希望的路径为 /user/123
或 /user/456
。后边的值为用户 id 或其他值。
配置路由
routers:[ { path: '/user/:id', component:()=>{ import('../views/user.vue') } } ]
添加路由
<router-link to="/user/123"> user:123 </router-link> <router-link to="/user/456"> user:456 </router-link> //动态设置后边id值 <router-link :to=" '/user/'+id "> user:{{ id }} </router-link>
获取后边动态值
this.$route.params.id
此处的 id 是配置路由处设置的 id ,只要保持一致就可以了
方式二:使用 query 进行传参
<router-link to="/user?id=123"></router-link> //取值时 this.$route.query.id
另外,this.$router.addRoutes([])
也可以添加动态路由,里面传的是一个数组,与 routes
配置一样。
懒加载通俗的讲就是使用的时候再加载,不使用的时候不加载。
打包构建应用程序的时候,js包会变得很大,影响加载速度,如果我们能把不同路由对应的组件分割成不同的代码块,然后访问路由的时候才加载对应的组件,这样就更加高效了。
路由懒加载到底做了什么呢?主要作用就是将路由对应的组件打包成一个js代码块,只有路由访问的时候,才加载对应的 js 。
//直接引用的 import Home from './component/home' const routes = [ { path:'/home', component:Home } ] //懒加载 const routes = [ { path:'/home', component:()=>{ import('./component/home') } } ]
实际应用中,通常由多层嵌套的组件组合而成。
实现步骤:
第一:创建对应的子组件,并且在路由映射中配置对应的子路由。
第二:组件内部使用 router-view
标签
{ path: "/body", component: ()=> import( "../components/bodyLayout.vue"),, children:[ { path: "manager", component: ()=> import( "../components/blankView.vue"), children:[ { path: "user", component: ()=> import( "../views/manager/user.vue") }, ] }, ] }
访问 user
组件时,路由为:/body/manager/user
注意:嵌套路由设置 path 时,不能添加 “/”,否则路由就变了。
{ path: "/user", component: ()=> import( "../views/manager/user.vue") } //此时访问路由就变成了 " /user "
试着在main.js
打印 router
在任意组件内打印 this.$router
,打印结果如图:
我们发现两个结果是一模一样的。这样我们就不难理解下面的意思了。
router
为 VueRouter
实例,拥有自己的方法,如:使用 new VueRouter
创建的实例,想要导航到不同url,可以使用 router.push
,跳转方式中有介绍。
route 为当前活跃状态路由对象,有当前路由的信息,可以通过该对象,获取 path
、params
参数、query
参数、
、
name
matched
、hash
为什么使用导航守卫?我们来考虑一个需求:在 SPA应用中,网页标题跟着页面切换如何变动?
// 在对应的组件内添加 created(){ document.title="测试" } 访问该组件时,标题自动切换为 ”测试“
如果使用上述方法,那么对应已开发的组件有多少个,我们就得添加多少次,实在是太麻烦了,所以我们要借助路由守卫,统一修改,也便于维护。
1>、使用 router.beforeEach
注册一个全局前置守卫,只要路由变动时,都会经过它。beforeEach 接收的参数是一个函数,包含的参数有三个。
router.beforeEach((to,from,next)=>{ // 路由从 from 跳转到 to // 我们只需要在路由上增加一个 name属性就可以了 document.title = from.name next() })
注意:上述三个参数顺序不能改变。next 不能丢,必须添加,否则页面跳转的时候没法到下一步,卡在空白区域。
2>、使用 router.afterEach
注册一个全局后置守卫。
router.afterEach((to,from)=>{ console.log('后置守卫') })
这两个守卫都是全局守卫,afterEach
是在路由跳转完成才执行的,所以不需要 next
。参数只有两个。
路由配置上直接定义的守卫,用法与全局守卫一致,只是将其放在其中一个路由对象中,只有这个路由下起作用。
{ path: "/test", name: "测试", component: ()=> import( "../views/manager/test.vue"), beforeEnter:(to,from,next)=>{ console.log('test进入前') next() } }
这些守卫与全局前置守卫的方法参数是一样的。
可以在路由组件内直接定义路由导航守卫,定义在组件内的就是组件内守卫。
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` } }
注意:beforeRouteLeave
离开路由时执行,必须添加 next
,否则无法正常跳转到下一个路由。
切换路由的时候页面每次都会重新渲染,我们有的组件会存在一些数据需要保留,不希望来回切换时每次都重新渲染,所以就使用 keep-alive
包裹组件,这样只有第一次执行加载时会执行 created mounted
等钩子函数。
keep-alive
是 Vue
内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
<div id="app"> <router-link to="/home">home</router-link> <router-link to="/login">login</router-link> <keep-alive> <router-view></router-view> </keep-alive> </div>
添加 keep-alive
组件,切换的时候,组件只会在第一次的时候渲染组件,之后进入不会重新渲染。
activated(){ console.log('activated') }, deactivated(){ console.log("deactivated") }
这两个函数,只有组件被保持了状态,使用keep-alive
时,才是有效会执行的。
keep-alive生命周期执行顺序:
created -> mounted -> activated
deactivated
在退出后才会触发
keep-alive 有两个非常重要的属性:
include
- 字符串或正则表达式,只有匹配组件的时候才会被缓存
exclude
- 字符串或正则表达式,任何匹配的组件都不会被缓存
<keep-alive include="test"> <router-view></router-view> </keep-alive> //test组件 添加name属性 <template> <div> test </div> </template> <script> export default { name:'test' } <script>
此时只有 test
组件会被缓存,其他任意组件都不会缓存。
如果还有其他组件同时需要被缓存,include
可添加多个值,只用逗号隔开,但不能添加空格。
<keep-alive include="test,user"> <router-view></router-view> </keep-alive>
exclude的使用:
<keep-alive exclude="test,user"> <router-view></router-view> </keep-alive>
正好与上实例相反,只有 test
,user
两个组件不被缓存,其他的被缓存。