zoukankan      html  css  js  c++  java
  • vue 关于生命周期

    序言:

      1. vue 单组件的生命周期;

      2. vue 父子组件的生命周期;

      3. axios 异步请求 与 vue 的组件周期;

    一、vue 每个组件的生命周期

      关于每个组件的生命周期,官方文档里也提供了,网上也能搜到各路大神们的相关文章,这里不赘述,贴一个网址以及简单总结。

      Vue的生命周期 - 转自浅白

      简单总结:

        1.beforeCreate 此时 $el、data 的值都为 undefined ;

        2.created 此时可以拿到 data 中的值,但是 this.$el 任然是 undefined ;

        3.beforeMounte 此时可以打印 this.$el, 但是当中的 {{ data }} 还没有被替换,this.$el 是虚拟节点;

        4.mounted data,$el 均可以被打印,{{ data }} 也已经被替换成正式的 Dom, vue实例被挂载在真实的 dom 树上;

        5.beforeUpdate/updated

        6.beforeDestroy/destroyed

      一张简单示意图:

    二、父子组件的生命周期

      在项目中,平时可能更多的是关心单个组件的生命周期。

      最近手头的一个项目有一个优化:入口是一个平台(父系统),在这个父系统中点击按钮进入子系统的相应模块,当然,窗口打开方式是 _blank,父子系统之间的通信流程是,vue路由导航守卫根据 cookie 中的 token 设置,cookie 中如过有 token ,正常跳转,没有 token ,通过 H5 postMessage() / window.addEventListener('message', function(event){}, false) 来向父系统获取 toke, 在回调函数 function(event){} 中,将获取的token 首先放入 cookie 中,这样,下次 axios 请求时可以从 cookie 中取值并设置请求头,其他用户信息等在依此根据 token 去获取并存入 localStorage 中。

      不过问题就出现在 _blank 上(这是技术选型的时候没有考虑的,vue 比较适合 spa 项目),如果我先以一个账号信息进入子系统的一个模块(打开了一个新标签页),然后不关闭这个页面回到父系统的窗口,切换账号登陆父系统,任然点击进入同一个子系统的模块,此时会发现,这次进入时拉取的数据是依据 localStorage 中存放的前一个 userId 拉取的,但是,F5 刷新一下就能拉取正确信息,这就不合理了。

      后来阅读源码,发现,子系统中最基础的子组件中某些关键信息都是从 localStorage 中获取,而每个模块中都有 postMessage 方法,只不过这个方法是在父组件的 mounted 阶段才调用,这就是导致了上面的换账号后进入模块,子组件根据 localStorage/cookie 中的前账号信息先去拉取数据,完成初始化,到所有子组件的初始化完成后父组件才执行 mounted 中 postMessage 方法,获取并在 cookie 中设置后账号的 token  ,然后 F5 刷新时,所用的请求头中是后账号的 token,才拉取到正确的数据。

      这里面的父子组件的生命周期是:

      1.加载渲染过程:

    父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
    

       2.子组件更新过程

    父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
    

       3.父组件更新过程

    父 beforeUpdate -> 父 updated
    

       4.销毁过程

    父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
    

      明白了父子组件的渲染时间点,那在父组件 beforeCreate / created / beforeMount 时调用 postMessage 方法不就可以了吗?

      答案是不行。为什么?因为异步。我尝试了,在 父组件 的上面三个阶段内调用 postMessage 方法,其回调函数的执行一定会落后于子组件的渲染挂载,即 子组件凭借 cookie / loaclStorage 里面的前账号信息拉取数据 一定会在 后账号的 token 被存放到 cookie 中之前执行,这是其一;其二,因为 vue 推荐的是 axios 请求模块,这是一个异步请求模块,即使在父组件三个阶段内去更新用户信息,这一步依然会落后于子组件的渲染挂载。

      那么如何解决?

      我的解决办法:组件内路由钩子 beforeRouteEnter(to, from, next)

      在这个钩子中,调用 postMessage,获取 最新 token, 在其回调函数中,凭借新的 token, 使用 jquery(本来项目中有依赖)发送 一个拉取用户关键信息的 ajax 请求,这个请求设置成同步,获取到数据后,将相关信息更新到 cookie / localStorage 中,确保后续的请求都是依据最新的用户信息。在确保上面的操作全部完成之后,next() 到想要的路由上去。

      当然,es 7 的 async/await api 可以替换调使用 jquery 的部分,从而解决问题。2020/04/20

      尾声:

      axios 中没有同步请求,$.ajax 也不推荐使用同步请求。需求如此,尚未找到更好的解决办法,vue 仍需探索。

  • 相关阅读:
    LeetCode 18. 4Sum (四数之和)
    开运算、闭运算、形态学梯度、顶帽、黑帽
    膨胀和腐蚀
    四种滤波方式
    关于平滑处理及图像滤波与滤波器
    27、简述redis的有哪几种持久化策略及比较?
    26、redis中默认有多少个哈希槽?
    25、如何实现redis集群?
    大聊Python----Select解析
    大聊Python----IO口多路复用
  • 原文地址:https://www.cnblogs.com/cc-freiheit/p/9876565.html
Copyright © 2011-2022 走看看