面试官:聊下vue的生命周期

当我们跳转页面的时候,需要在页面加载中发请求,拿到数据。请求函数可以写在上一个页面的点击事件,但是一般不会这样写,因为数据量太大了,数据放在浏览器地址栏不够放,所以就是来到这个页面去发请求,我们一般都是放在当前页面的生命周期中发请求

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中

路由有三大钩子函数,如下

  • 全局守卫

    1. router.beforeEach全局前置

      这个钩子的回调中有三个参数,分别为to, from, next。通常我们可以用这个来判断用户是否登录,如果没有登录去其他页面就送回登录页面

      vbnet 复制代码
      router.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的值

      当然,你还可以用这个前置钩子设置页面的标题

      javascript 复制代码
      import { 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是专门用于存放一些参数信息,是路由的特殊标记

    2. router.beforeResolve全局解析

      解析钩子和全局前置区别不大,解析钩子是在路由被解析,代码被编译之前触发。

    3. router.afterEach全局后置

      这个钩子的回调函数只有两个参数,没有next。after就是路由跳转之后去干什么事情,用处很少。

    这三个钩子可以用跳远来形容,beforeEach是起跳前,beforeResolve是悬空中,afterEach是落地后,用的最多的钩子就是第一个beforeEach

  • 独享守卫

    刚刚的守卫是全局的,只要是路由跳转,都可以影响到。独享路由只能影响自身,配置方法如下,这里给about页面配置

    javascript 复制代码
    const 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

  1. onBeforeRouteLeave

    离开页面前做一些操作,比如,离开页面前,弹出你确定想要离开

    javascript 复制代码
    import { onBeforeRouteLeave } from 'vue-router';
    
    onBeforeRouteLeave((to, from, next) => {  
        console.log(to, from);
        const flag = window.confirm('你确定要离开这个页面吗?')
        if (flag) {
            next()
        }
    })

    window.confirm()是js自带的弹出框

  2. 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>

我们可以在首页中写入钩子onActivatedonDeactivated测试下是否真被缓存了

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,这里有几十位一心去大厂的友友可以相互鼓励,分享信息,模拟面试,共读源码,齐刷算法,手撕面经。来吧,友友们!

相关推荐
崔庆才丨静觅1 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60612 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了2 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅2 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅2 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅3 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment3 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅3 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊3 小时前
jwt介绍
前端
爱敲代码的小鱼3 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax