Vue中父子组件生命周期执行顺序初探

<p><code></p> <blockquote><p>如今前端框架都流行组件化,页面元素都可以使用组件进行高度概括,那么处理组件之间的关系就如同处理页面架构一样重要。正确理解组件之间的关系,才能让代码按照我们与预料方式工作。最近参与了一个Vue.js的项目,在处理父子嵌套组件之间关系时遇到了较大的阻力,虽然问题最后解决了,但是以花费大量时间为代价的,记录在这里,希望下次不踩同样的坑,能更高效的处理此类问题。</p></blockquote> <h2 id="articleHeader0">0 问题描述</h2> <p>同react,vue组件也有一套完整的生命周期,不同阶段有不同的分工。总体来讲经常会用的生命周期钩子有以下几种:</p> <ul> <li>created</li> <li>mounted</li> <li>destroy</li> </ul> <p>通常会在这些钩子中处理一些异步请求,最常见的就是发起网络请求调用api获取数据。 </p> <p>这里有个问题:在单一组件中,钩子的执行顺序是<code>created -&gt; mounted -&gt; destroyed</code>,但当父子组件嵌套时,父组件和子组件各拥有各自独立的钩子函数,这些父子组件的这些钩子是如何交融执行,且执行顺序又是怎样的呢?</p> <p>最近开发中遇到的一个“诡异”的问题,就是由于对父子组件生命周期钩子执行顺序理解不透彻引起的。问题是这样的:有一个组件有由一系列子组件组成,子组件又被分解成组件,这样下来就构成了三级组件。需求是在组件显示在页面上之后,再将数据初始化进行回显。父组件获取数据后传递到子组件,要求子组件根据这个值将内部元数据进行过滤和加工。那么在子组件中什么时机下才能获取父组件传递过来的新值呢?。</p> <div class="google-auto-placed ap_container" style="text-align: center; width: 100%; height: auto; clear: none;"><ins data-ad-format="auto" class="adsbygoogle adsbygoogle-noablate" data-ad-client="ca-pub-6330872677300335" data-adsbygoogle-status="done" style="display: block; margin: auto; background-color: transparent;"><ins id="aswift_4_expand" style="display:inline-table;border:none;height:175px;margin:0;padding:0;position:relative;visibility:visible;width:697px;background-color:transparent;"><ins id="aswift_4_anchor" style="display:block;border:none;height:175px;margin:0;padding:0;position:relative;visibility:visible;width:697px;background-color:transparent;"><iframe width="697" height="175" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" onload="var i=this.id,s=window.google_iframe_oncopy,H=s&amp;&amp;s.handlers,h=H&amp;&amp;H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&amp;&amp;d&amp;&amp;(!d.body||!d.body.firstChild)){if(h.call){setTimeout(h,0)}else if(h.match){try{h=s.upd(h,i)}catch(e){}w.location.replace(h)}}" id="aswift_4" name="aswift_4" style="left:0;position:absolute;top:0;border:0px;width:697px;height:175px;"></iframe></ins></ins></ins></div> <p>我的做法是这样的:最高层父组件的<code>mounted</code>中发起请求获取数据,通过vue的响应机制以props的形式传递到子组件,在子组件的<code>mounted</code>中拿到对应的props进行处理。这样做法要求父组件的<code>mounted</code>时机先于子组件的<code>mounted</code>,但事实是这样吗?显然不是。</p> <p>这样导致的问题就是,数据无法正确的回显。</p> <h2 id="articleHeader1">1 探究</h2> <p>探究的方法是:写一个有父子嵌套关系的组件,分别在他们的钩子函数中打印日志,观察执行顺序。得到的结果如图所示,父组件先创建,然后子组件创建;子组件先挂载,然后父组件挂载。<br /><span class="img-wrap"><img data-src="/img/bVbePUv?w=302&amp;h=298" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="图片描述" title="图片描述" style="cursor: pointer;"></span></p> <p>子组件挂载完成后,父组件还未挂载。所以组件数据回显的时候,在父组件<code>mounted</code>中获取api的数据,子组件的<code>mounted</code>是拿不到的。</p> <p>仔细看看父子组件生命周期钩子的执行顺序,会发现<code>created</code>这个钩子是按照从外内顺序执行,所以回显场景的解决方案是:在created中发起请求获取数据,依次在子组件的created中会接收到这个数据。</p> <h2 id="articleHeader2">2 结论</h2> <p>Vue父子组件生命周期钩子的执行顺序遵循:从外到内,然后再从内到外,不管嵌套几层深,也遵循这个规律。</p> <blockquote><p>组件化的设计思路大抵相同,React中父子组件生命周期钩子执行顺序,具体没做探究,但是值得一提的是react父组件的componentDidMount也是晚于子组件componentDidMount执行的。</p></blockquote> <h2 id="articleHeader3">3 其他</h2> <p>关于回显,问题在于如何在子组件中知道远程数据回来了,并且通过对远程数据的加工处理,最终形成正确的回显。处理按照钩子的顺序获取数据,在vue中还有一个特性<code>watch</code>,是否可以通过watch属性的方式来更新回显呢?这种方法有待于探究。</p> <p></code></p>
脚本宝典为你提供优质服务
脚本宝典 » Vue中父子组件生命周期执行顺序初探

发表评论

提供最优质的资源集合

立即查看 了解详情