目录
- 介绍
- 路由跳转和传参
- 解决路由重复点击路由沉积的问题
- 解决路由跳转后不能回到顶部的页面顶部的问题
- 路由导航守卫和案例展示
- 访问外部链接
介绍
vue-router相当于vue内部跳转链接,将需要切换的页面在vue-router里注册,在项目里配置就能完成页面的切换,它不仅能完成项目的切换,还能实现参数的传递,它还有个很重要的功能路由导航守卫(导航守卫分为前置导航守卫,后置导航守卫,组件内置导航守卫,常用就是前置导航守卫,设置用户登录可访问的界面和未登录可访问的界面,也相当于二次拦截,(axios请求拦截器是第一次拦截))。
路由跳转和传参
重点:
在vue-router中,有两大对象被挂载到了实例this;
$route(只读、具备信息的对象);
$router(具备功能的函数);
1.router-link(类似a标签)
路由配置:
// 路由配置 | |
{ | |
path: '/pkproperties', // 路径 | |
name:'pkproperties', // 路由名,path路径必写,用name跳转的时候是根据name名找到path进行跳转 | |
component: () => import('@/views/pkproperties'), // 组件(组件文件名为index的可省略),路由懒加载写法 | |
redirect: '', // 路由重定向,就是当一个页面需要切换多个路由的时候,这里面填的是首次进入页面展示的路由组件地址 | |
hidden: true, | |
children: [] // 嵌套路由,当一页有很多路由需要切换的时候,就需要用到嵌套路由 | |
}, | |
// 组件内使用 | |
<router-link to="/pkproperties">点击跳转</router-link> // path路径跳转 | |
<router-link to="{name:'pkproperties',query:{id:}}">点击跳转</router-link> // 使用命名路由name跳转 |
传参配置:
{ | |
path: '/pkproperties', // 路径 | |
name:'pkproperties', // 路由名,path路径必写,用name跳转的时候是根据name名找到path进行跳转 | |
component: () => import('@/views/pkproperties'), // 组件(组件文件名为index的可省略) | |
hidden: true | |
}, | |
// 使用命名路由传参,可以传递基本数据类型和数组和对象 | |
<router-link to="{name:'pkproperties',query:{id:}}">点击跳转</router-link> // name名跳转,query传递参数 | |
<router-link to="{name:'pkproperties',params:{id:}}">点击跳转</router-link> // name名跳转,params传递参数 | |
this.$route.query.id // 获取传递的参数(.传递参数的键名) | |
this.$route.params.id // 获取传递的参数(.传递参数的键名) |
2.编程式路由跳转(最常用的,不受时机、条件的限制)
路由配置:
{ | |
path: '/pkproperties', // 路径 | |
name:'pkproperties', // 路由名,path路径必写,用name跳转的时候是根据name名找到path进行跳转 | |
component: () => import('@/views/pkproperties'), // 组件(组件文件名为index的可省略) | |
hidden: true | |
}, |
传参配置:
methods:{ | |
onSkipTransferParameters(){ | |
// params传参 | |
this.$router.push({ | |
name: "pkproperties", | |
params: { | |
name: '小明', | |
id:, | |
}, | |
}); | |
onSkipTransferParameters(){ | |
// query传参 | |
this.$router.push({ | |
name: "pkproperties", | |
query: { | |
name: '小明', | |
id:, | |
}, | |
}); | |
} | |
// 获取传递的参数 | |
this.$route.params.name // 获取就是在当前跳转的组件内调用$route实例,是用params就.params.键名获取值 | |
this.$route.query.name // 获取就是在当前跳转的组件内调用$route实例,是用query就.query.键名获取值 |
query传参在刷新界面后传递的数据不会丢失,params传递的参数刷新界面后会丢失参数。
3.路由重定向redirect需要用到传参的业务
{ path:"/", redirect: {path:"pkproperties", query:{Pid:''}} }, | |
{ path:"pkproperties", component: ()=>import("../views/pkproperties") } |
解决路由重复点击路由沉积的问题
// 把这段代码直接粘贴到router/index.js中的Vue.use(VueRouter)之前 | |
const originalPush = VueRouter.prototype.push; | |
VueRouter.prototype.push = function (location) { | |
return originalPush.call(this, location).catch(err => { }) | |
}; |
注意:一定要写在 Vue.use(VueRouter)之前否则无效
解决路由跳转后不能回到顶部的页面顶部的问题
在跳转到的组件里配置下面的代码即可
mounted() { | |
/** | |
* 路由跳转回到顶部 | |
*/ | |
// chrome | |
document.body.scrollTop =; | |
// firefox | |
document.documentElement.scrollTop =; | |
// safari | |
window.pageYOffset =; | |
}, |
路由导航守卫和案例展示
路由前置导航守卫(beforeEach)
// 全局导航守卫beforeEach | |
router.beforeEach((to, from, next) => { | |
// to要到哪个路由去 // from从哪个路由来 | |
// next下一步(无论失败与否都要调用,否则会阻止程序继续执行) | |
} |
案例1中使用(拦截未登录用户和白名单设置):
permission.js文件下配置(permission文件最好和main文件在同一目录下创建)
import router from './router' | |
import { getToken } from '@/common/TokenStore' | |
const whiteList = ['/login', '/register'] // 白名单登录注册界面无需验证Token是否登录直接放行 | |
// 全局导航守卫beforeEach | |
router.beforeEach((to, from, next) => { | |
// 白名单中路由直接放行 | |
if (whiteList.indexOf(to.path) !== -) {next() | |
return | |
} | |
// 判断需要登录身份认证的路由 | |
const token = getToken() // 获取token | |
if (token) {next() | |
} else {next(`/login`) // 如果登录不存在,重定向到登录界面 | |
} | |
}) |
main.js文件下引入即可
import './permission' // 引入即可
案例2中使用(设置Tokne失效实现拦截,Tokne失效就导航会登录界面重新登录,未失效就不执行操作)
login.vue(登录组件登录成功后保存Token和保存获取Token的当前时间戳在本地)
methods: { | |
// 登录 | |
handleLogin() { | |
this.$axios.post('/api/Login',{ | |
username: this.loginForm.username, // 用户名 | |
password: this.loginForm.password // 密码 | |
}).then(res => { | |
if(res.data.code !=) return this.$message.error(res.data.message) // code 不等于0,返回失败的结果,(这的判断参数是根据后端返回的数据进行的,不是固定的) | |
if(res.data.code ==){ | |
this.$message.success('登录成功') | |
// 存储token开始时间 | |
window.localStorage.setItem('tokenStartTime',new Date().getTime()) | |
// 存储token | |
window.localStorage.setItem('token',res.data.data.token) | |
this.$router.push('/home/ks') | |
}else { | |
this.$message.error('登录失败') | |
} | |
}) | |
} | |
} |
permission.js(将保存的Token获取时间和当前时间进行一个差值的比较,如果小于我们设定的Token失效时间,就证明登录没有过期可继续访问,如果大于就登录过期Token失效需要重新登录获取。)
// 导入element提示语的组件可以去element-ui查看用法,这是按需引入的 | |
import { Message | |
} from 'element-ui' | |
// 添加请求拦截器 | |
// 拦截器的第二部分,第一部分在main.js里面 | |
router.beforeEach((to, from, next) => {// 获取存储localStorage的token | |
let token = window.localStorage.getItem('token')// 获取存储token的开始时间 | |
const tokenStartTime = window.localStorage.getItem('tokenStartTime')// 后台给出的token有效时间为一天,这个是后端给的时间以后端为准 | |
const timeOver =// 获取当前时间 | |
let date = new Date().getTime()// 当前时间减去获取Token的时间如果大于说明是token过期了 | |
if(date - tokenStartTime > timeOver) { token = null // Token过期赋值为null | |
}// 如果token过期了 | |
if (!token) { if (to.path == '/login') return next() | |
// 注意要import element的Message组件 | |
Message.error("登录状态过期,请重新登录") | |
return next('/login') | |
// 如果token没有过期,又是选择了登录页面就直接重定向到首页,不需要重新输入账户密码 | |
} else if (to.path == '/login') { return next('/home/ks') | |
}next() | |
}) | |
export default router |
全局后置守卫(afterEach)
router.afterEach((to,from)=>{<!--{cke_protected}{C}%C!%2D%2D%20%2D%2D%3E-->})
组件内守卫(相当于给组件增加生命周期)
beforeRouteEnter 进入组件之前
beforeRouterEnter(to,from,next){}
beforeRouteUpdate 组件被复用时调用
beforeRouterUpdate(to,from,next){}
beforeRouteLeave 离开组件时调用
beforeRouteLeave(to,from,next){}
访问外部链接
vue内部跳转可以通过vue-router中的this.$router.push()和rout-link 来实现,这里在说一下想要访问外部链接的方法
1.window.location.href = url(不新开一个页面,直接在当前页面跳转)
methods:{onSkip(){ | |
window.location.href = "http://xxx.xxx.xxx" | |
} | |
} |
2.window.open(“url”, “_blank”)(打开一个新页面跳转)
methods:{onSkip(){ | |
window.open("https://xxx.xxx.xxx/", "_blank"); | |
} | |
} |
3.手动创建a标签,然后默认点击
var a = document.createElement("a"); a.setAttribute("href", "www.baidu.com"); | |
a.setAttribute("target", "_blank"); | |
a.click(); |