当我们跳转页面的时候,需要在页面加载中发请求,拿到数据。请求函数可以写在上一个页面的点击事件,但是一般不会这样写,因为数据量太大了,数据放在浏览器地址栏不够放,所以就是来到这个页面去发请求,我们一般都是放在当前页面的生命周期中发请求
vue的生命周期有如下这些
其中
这四个钩子函数你基本上很少用上,一般都是用于调试。error和两个render都是捕获错误的,server是作服务端渲染的。
今天来认识下这些钩子函数
钩子函数就是生命周期函数,所谓生命周期就是让函数在页面加载的过程中自动执行,语法都是接受一个回调
vue的代码先会被去读到,然后进行编译,template代码浏览器是读不懂的,因此需要先进行编译,编译完就开行进行挂载,当vue代码片段被拿去挂载mount
,生命周期就会执行
挂载是main.js的职责,挂载就是把指定的template的代码放到index.html中去渲染
onBeforeMount()
onBeforeMount翻译过来就是挂载之前,也就是说此时的vue代码已经被编译完毕了
onMounted()
onMounted就是挂载之后
我们不妨看看下面的打印顺序
xml
<script setup>
import { onMounted, onBeforeMount} from 'vue';
console.log('hello')
onMounted(() => {
console.log('onMounted'
}
onBeforeMount(() => {
console.log('onBeforeMount')
}
</script>
console.log放在全局中执行,这个执行是在编译之后执行的,vue生命周期的template需要先编译再挂载,整个过程是比全局慢一步的,因此和钩子函数相比,全局函数是优先执行的
这里故意将onBeforeMount
放在onMounted
函数后面,就是为了证明onBeforeMount
一定是优先于onMounted
的执行,无论代码位置
我们再来试试看在这三个打印中分别附上一个dom结构的打印
在全局中没有获得这个dom结构,如何理解:拿到dom结构指的是浏览器,在执行这个代码的时候,页面还没有挂载,是拿不到dom结构的,所以这个打印如果你放在onBeforeMount
也是无法打印的,只有onMounted
才可以拿到。
问题来了,从后端发请求的代码应该放在这三个中的哪一个
其实三个都可以,但是我们习惯性的会放在onMounted中,因为有些数据拿到之后可能会操作dom结构
onUnmounted()
onUnmounted是卸载的意思,所以这个钩子就是在页面卸载的时候执行,其实就是离开页面的时候。
这个钩子函数的用处不多,不过当我们如果想要掐灭当前页面的定时器的时候可以用这个钩子,因为有时候离开当前页面的时候定时器还会存在,影响性能。
onUpdated()
onBeforeUpdate()
这两个钩子都是在数据源更新的时候使用,只要响应式数据发生变更,就会触发这个钩子的执行,有点类似watch
监听器
接下来聊聊路由里面的钩子函数,这才是今天的主角。其实就是围绕着下面这些来讲,路由官网的进阶教程
路由的钩子函数
路由的钩子函数一般写入路由配置文件中router/index.js
,当然你也可以写在main.js中
路由有三大钩子函数,如下
-
全局守卫
-
router.beforeEach全局前置
这个钩子的回调中有三个参数,分别为
to
,from
,next
。通常我们可以用这个来判断用户是否登录,如果没有登录去其他页面就送回登录页面vbnetrouter.beforeEach((to, from, next) => { if (to.path !== '/') { const isLogin = localStorage.getItem('isLogin') // 读取isLogin if (isLogin) { next() } else { router.push('/login') } } next() })
当然这仅仅是前端的判断规则,其实单单这个方法并不严谨,需要前后端一起配合才严谨,因为有些用户可能直接右键页面来到应用下给
Local storage
塞一个isLogin
为true的值当然,你还可以用这个前置钩子设置页面的标题
javascriptimport { createWebHistory, createRouter } from 'vue-router' const routes = [ { path: '/', name: 'home', component: () => import('../views/Home.vue'), meta: { title: '首页' } }, { path: '/about', name: 'about', component: () => import('../views/About.vue'), meta: { title: '关于' } } ] const router = createRouter({ history: createWebHistory(), routes }) router.beforeEach((to, from, next) => { document.title = to.meta.title if (to.path !== '/') { const isLogin = localStorage.getItem('isLogin') if (isLogin) { next() } else { alert('未登录,不许跳页面') return } } next() }) export default router
meta是专门用于存放一些参数信息,是路由的特殊标记
-
router.beforeResolve全局解析
解析钩子和全局前置区别不大,解析钩子是在路由被解析,代码被编译之前触发。
-
router.afterEach全局后置
这个钩子的回调函数只有两个参数,没有next。after就是路由跳转之后去干什么事情,用处很少。
这三个钩子可以用跳远来形容,beforeEach是起跳前,beforeResolve是悬空中,afterEach是落地后,用的最多的钩子就是第一个beforeEach
-
-
独享守卫
刚刚的守卫是全局的,只要是路由跳转,都可以影响到。独享路由只能影响自身,配置方法如下,这里给about页面配置
javascriptconst routes = [ { path: '/', name: 'home', component: () => import('../views/Home.vue'), meta: { title: '首页' } }, { path: '/about', name: 'about', component: () => import('../views/About.vue'), meta: { title: '关于' }, beforeEnter: (to, from, next) => { console.log(to, from); next() } } ]
你可以在里面写逻辑,比如特定页面弹出广告
-
组件内的守卫
组件内的守卫写入指定的页面中,写之前记得引入。新语法只有下面这两个,以前还有一个
onBeforeRouteEnter
-
onBeforeRouteLeave
离开页面前做一些操作,比如,离开页面前,弹出你确定想要离开
javascriptimport { onBeforeRouteLeave } from 'vue-router'; onBeforeRouteLeave((to, from, next) => { console.log(to, from); const flag = window.confirm('你确定要离开这个页面吗?') if (flag) { next() } })
window.confirm()是js自带的弹出框
-
onBeforeRouteUpdate
如果两个页面之间共用了一个组件,并且互相跳转,就可以用这个Update方法写逻辑
keep-alive
在开发vue项目的时候,很多组件是没有必要再次渲染的。多个页面公用一个组件,跳转页面的时候就不需要再次渲染,就没必要再次加载公共组件的代码
因为跳转路由的时候页面内所有的组件都是会重新销毁加载的
keep-alive的作用就是用来包裹需要缓存的组件,留下缓存就是不会重新加载,起到一个性能优化
的作用
这里我用两个页面首页,和关于页面,然后缓存首页模拟下,语法如下,写在App.vue
中
xml
<template>
<div>
<nav>
<router-link to="/">首页 | </router-link>
<router-link to="/about">关于</router-link>
</nav>
<router-view v-slot="{ Component }">
<keep-alive :include="['Home']">
<component :is="Component" />
</keep-alive>
</router-view>
</div>
</template>
<script setup>
</script>
<style lang="css" scoped></style>
我们可以在首页中写入钩子onActivated
和onDeactivated
测试下是否真被缓存了
xml
<template>
<div>
<p>home page</p>
</div>
</template>
<script setup>
import { onMounted, onActivated, onDeactivated } from 'vue';
onMounted(() => {
console.log('home的onMounted');
})
onActivated(() => { // 当被缓存的组件再次生效时触发
console.log('home的onActivated');
})
onDeactivated(() => { // 当组件被缓存起来并离开时触发
console.log('home的onDeactivated');
})
</script>
<style lang="css" scoped>
</style>
第一次进入首页时,会触发onMounted
,之后从其他页面再次进入时就不再触发onMounted
,因为首页被缓存了起来,压根没有被卸载(卸载是默认的效果)
onActivated()
onActivated其实就是缓存版的onMounted,被缓存的组件加载时生效
onDeactivated()
onDeactivated其实就是缓存版的onUnmounted,被缓存的组件离开时生效
这两个钩子都不需要进行再次解析组件,因为针对的组件都是已经被缓存过的。就相当于你没扔掉,而是放进了一个口袋,用时拿起,不用时放入。
所以这两个钩子一定需要有keep-alive的出现,否则用不上
最后
vue里面的生命周期清除这些足够拿去面试了,其实面试官最想听你讲的就是onAcivated和onDeactivated,很容易理解
另外有不懂之处欢迎在评论区留言,如果觉得文章对你学习有所帮助,还请"点赞+评论+收藏"一键三连,感谢支持!
本次学习代码已上传至本人GitHub学习仓库:github.com/DolphinFeng...
假如您也和我一样,在准备春招。欢迎加我微信Dolphin_Fung,这里有几十位一心去大厂的友友可以相互鼓励,分享信息,模拟面试,共读源码,齐刷算法,手撕面经。来吧,友友们!