1.vue路由守卫
路由守卫也叫路由钩子函数,它是在路由跳转过程中调用的函数,通过路由守卫可获取路由信息和阻止路由跳转。
1.1 路由守卫三种分类
1.1.1 组件内的路由守卫
beforeRouteEnter()、beforeRouteLeave()、beforeUpdate()
export default {
name: "About",
data() {
return {
keyword: ""
}
},
methods: {
search() {
// 点击搜索按钮时,跳转到搜索页(当前页)
this.$router.push("/search");
// 如果当前页直接跳转当前页会报错
// 原因:原路由url和新路由url完全一致,会报错,路由避免重复跳转
// 解决方案:在路由跳转时传入一个参数,参数不同就不会报错
this.$router.push("/search?key=" + this.keyword)
}
},
// 在组件中有三个路由首位函数
beforeRouteEnter(to, from, next) {
// 在路由跳转到到这一页之前,执行这个函数
console.log("路由即将进入about");
// 默认,这个守卫函数会阻止路由跳转到这一页
console.log(from.path, to.path);
next();
},
beforeRouteLeave(to, from, next) {
// 在路由将要从这一页离开之前,执行这个函数
// 默认,这个守卫函数会阻止路由离开
next(); //允许路由离开
},
beforeEouteUpdate(to, from, next) {
// 当路由更新之前,执行这个函数,当前页跳转到当前页表示路由更新
console.log("路由更新");
},
}
1.1.2 全局路由守卫
beforeEach()、afterEach()
全局路由守卫是通过路由配置对象router调用
// 全局路由守卫通过路由配置对象router调用
router.beforeEach(function(to, from, next) {
console.log("全局守卫:路由跳转之前");
next()
})
router.afterEach(function() {
console.log("全局守卫:路由跳转之后");
// 路由跳转后调用此函数,不需要next,无法拦截路由
})
1.1.3 单个路由守卫
beforeEnter()
单个路由守卫是在作为路由的配置对象中,只对当前路由起效
const routes = [{
path: '/',
name: 'home',
component: HomeView,
// 单个路由守卫写在路由的配置对象中,只能对当前路由起效,是对象中函数
beforeEnter: (to, from, next) => {
console.log("主页守卫:", from.path, to.path);
next()
}
}
]
1.2 路由守卫的参数
- to:表示路由跳转的目标信息对象(到哪儿去)
- from:表示路由跳转的来源信息对象(从哪儿来)
- next:回调函数,表示是否允许路由跳转,调用允许,不调用则禁止
1.3 路由守卫的使用场景
- beforeRouteEnter、beforeRouteLeave、beforeEach 这三个都是路由进入之前的守卫,这些路由守卫常用于做登录认证,在这里判断用户是否已经登录,如果已经登陆,调用next()允许进入,如果没有登录,不调用next(),禁止进入,主要针对一些需要登陆状态才能访问的 页面,如:个人信息页
- beforeRouteLeave 是路由离开之前的守卫,在一些表单页面,在这个函数中提示,离开页面,填写的表单信息会丢失,如:在线测试页面,测试提交之前,不允许离开这一页
- beforeUpdate 是路由更新时调用的钩子函数,当路由路径来源和目标相同(当前页跳转当前页),并且参数不同时,会调用这个钩子,常用于搜索页,当搜索关键字改变时,在这里更新数据。
1.4 使用路由守卫注意问题
1.4.1 由于在任何组件中都能使用this.$router,所以全局路由守卫可以在任意组件中调用
1.4.2 brforeRouteEnter路由进入之前,组件还未创建,打印this是undefined,如果想用组件对象,可以在next()的回调中拿到组件对象
next( vm=>{ console.log(vm) })
1.4.3 this. r o u t e r 和 t h i s . router和this. router和this.route的区别
- this.$router是/src/router/index.js中创建的路由对象,全局唯一,用于编导式导航跳转和全局路由守卫
- this. r o u t e 是 路 由 跳 转 的 信 息 对 象 , 每 一 个 路 由 对 应 一 个 route是路由跳转的信息对象,每一个路由对应一个 route是路由跳转的信息对象,每一个路由对应一个route对象,用于路由传值和路由监听
1.4.4 路由监听和路由守卫的区别
- 路由监听:在组件中watch字段中监听$route,实现路由监听,只能监听路有变化,不能修改路由和限制路由跳转
- 路由守卫:使用路由钩子函数实现守卫,路由不知可以监听路由,还能控制路由跳转
1.4.5 当路由跳转时,跳转的路径和参数与当前完全一致,没有变化,不会调用路由钩子函数,会报错
报错:NavigationDuplicated: Avoided redundant navigation to current location: “/about?page=5”.
报错原因:原路由url和新路由url完全一致,会报错,路由避免重复跳转
解决方案1:在/src/router/index.js中添加如下代码:原理是捕获push函数报错,不抛出错误
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => {
//throw(err) // 抛出错误,控制台会显示错误信息, 如果不抛出,控制台不会报错
return err;
})
}
解决方案2:在路由跳转时传入一个参数,参数不同就不会报错
this.$router.push("/search?key=" + this.keyword)
2.vue-ajax请求
在vue项目中不能直接发送ajax请求,会被同源请求策略拦截,需要使用跨域代理器
2.1 代理服务器配置
ajax请求需要跨域的话,需要在vue.config.js中添加代理配置。以下是脚手架5.x版本的配置代码:
onst { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
publicPath: '/', // 启动页地址
outputDir: 'dist', // 打包的目录
lintOnSave: true, // 在保存时校验格式
productionSourceMap: false, // 生产环境是否生成 SourceMap
devServer: {
open: true,
host: 'localhost',
port: 8080,
proxy: {
"/myDouyu": {
target: "http://open.douyucdn.cn",
changeOrigin: true,
pathRewrite: {
"^/myDouyu": ""
}
}
}
}
})
- 在vue.config.js中的devServer.proxy字段代理服务器
- 这个文件是服务器的配置对象,所以这个文件的修改需要重启项目生效
2.2 fetch请求方式
在组件中的created钩子函数中使用ajax请求。
<script>
export default {
name: 'HomeView',
created() {
fetch("/myDouyu/api/RoomApi/live?page=1").then(res => {
res.json().then(res => {
console.log(res.data);
})
})
},
}
</script>
2.3 axios请求
2.3.1 局部使用axios请求
2.3.1.1 安装axios模块
cnpm i axios --save
2.3.1.2 在组件的script标签中导入axios
import axios from ‘axios’;
2.3.1.3 在当前组件的函数发起ajax请求
axios.get("/myDouyu/api/RoomApi/live", {
params: {
page: 1
}
}).then(res => {
console.log(res.data);
})
2.3.2 全局使用axios请求
2.3.2.1 安装axios模块
cnpm i axios --save
2.3.2.2 在main.js中导入axios并设置Vue原型
import axios from ‘axios’;
Vue.prototype.$axios = axios;
2.3.2.3 在任意组件中使用axios(添加$用于和组件内字段区分)
this.$axios.get("/myDouyu/api/RoomApi/live", {
params: {
page: 1
}
}).then(res => {
console.log(res.data.data);
})
3.vue中的props自定义属性
props属性验证写法,props的值是一个对象,对象中的键是属性名,值是属性的限制条件。组件标签自定义属性传值时要根据属性验证的数据类型传值,不然会报错。
export default {
name: 'HelloWorld',
props: {
msg: String
}
}