浅谈Vue初始化性能优化

前言

成都创新互联公司专注骨干网络服务器租用10多年,服务更有保障!服务器租用,川西大数据中心 成都服务器租用,成都服务器托管,骨干网络带宽,享受低延迟,高速访问。灵活、实现低成本的共享或公网数据中心高速带宽的专属高性能服务器。

一般来说,你不需要太关心vue的运行时性能,它在运行时非常快,但付出的代价是初始化时相对较慢。在最近开发的一个Hybrid APP里,Android Webview初始化一个较重的vue页面竟然用了1200ms ~ 1400ms,这让我开始重视vue的初始化性能,并最终优化到200 ~ 300ms,这篇文章分享我的优化思路。

性能瓶颈在哪里?

先看一下常见的vue写法:在html里放一个app组件,app组件里又引用了其他的子组件,形成一棵以app为根节点的组件树。


   

而正是这种做法引发了性能问题,要初始化一个父组件,必然需要先初始化它的子组件,而子组件又有它自己的子组件。那么要初始化根标签,就需要从底层开始冒泡,将页面所有组件都初始化完。所以我们的页面会在所有组件都初始化完才开始显示。

这个结果显然不是我们要的,更好的结果是页面可以从上到下按顺序流式渲染,这样可能总体时间增长了,但首屏时间缩减,在用户看来,页面打开速度就更快了。

要实现这种渲染模式,我总结了下有3种方式实现。第3种方式是我认为最合适的,也是我在项目中实际使用的优化方法。

第一种:不使用根组件

这种方式非常简单,例如:


  
  
  

抛弃了根组件,从而使A、B、C每一个组件初始化完都立刻展示。但根组件在SPA里是非常必要的,所以这种方式只适用小型页面。

第二种:异步组件

异步组件在官方文档已有说明,使用非常简单:


  
  

new Vue({
  components: {
    A: { /*component-config*/ },
    B (resolve) {
      setTimeout(() => {
        resolve({ /*component-config*/ })
      }, 0);
    }
  }
})

这里组件是一个异步组件,会等到手动调用resolve函数时才开始初始化,而父组件也不必等待先初始化完。

我们利用setTimeout(fn, 0)将的初始化放在队列最后,结果就是页面会在初始化完后立刻显示,然后再显示。如果你的页面有几十个组件,那么把非首屏的组件全设成异步组件,页面显示速度会有明显的提升。

你可以封装一个简单的函数来简化这个过程:

function deferLoad (component, time = 0) {
  return (resolve) => {
    window.setTimeout(() => resolve(component), time)
  };
}

new Vue({
  components: {
    B: deferLoad( /*component-config*/ ),
    // 100ms后渲染
    C: deferLoad( /*component-config*/, 100 )
  }
})

看起来很美好,但这种方式也有问题,考虑下这样的结构:


  
  
  
  
  
  

还是按照上面的异步组件做法,这时候就需要考虑把哪些组件设成异步的了。如果把A、B、C都设成异步的,那结果就是3个会首先渲染出来,页面渲染的过程在用户看来非常奇怪,并不是预期中的从上到下顺序渲染。</p><p><strong>第三种:v-if 和 terminal指令</strong></p><p>这是我推荐的一种做法,简单有效。还是那个结构,我们给要延迟渲染的组件加上v-if:</p><div><pre><app> <A></A> <B v-if="showB"></B> <C v-if="showC"></C> </app> </pre></div><div><pre>new Vue({ data: { showB: false, showC: false }, created () { // 显示B setTimeout(() => { this.showB = true; }, 0); // 显示C setTimeout(() => { this.showC = true; }, 0); } }); </pre></div><p>这个示例写起来略显啰嗦,但它已经实现了我们想要的顺序渲染的效果。页面会在A组件初始化完后显示,然后再按顺序渲染其余的组件,整个页面渲染方式看起来是流式的。</p><p>有些人可能会担心v-if存在一个编译/卸载过程,会有性能影响。但这里并不需要担心,因为v-if是惰性的,只有当第一次值为true时才会开始初始化。</p><p>这种写法看起来很麻烦,如果我们能实现一个类似v-if的组件,然后直接指定多少秒后渲染,那就更好了,例如:</p><div><pre><app> <A></A> <B v-lazy="0"></B> <C v-lazy="100"></C> </app></pre></div><p>一个简单的指令即可,不需要js端任何配合,并且可以用在普通dom上面,Nice!</p><p>在vue里,类似v-if和v-for这种是terminal指令,会在指令内部编译组件。如果你想要自己实现一个terminal指令,需要加上terminal: true,例如:</p><div><pre>Vue.directive('lazy', { terminal: true, bind () {}, update () {}, unbind () {} });</pre></div><p>这是vue在1.0.19+新增的功能,由于比较冷门,文档也没有特别详细的叙述,最好的方式是参照着v-if和v-for的源码来写。</p><p>我已经为此封装了一个terminal指令,你可以直接使用:https://github.com/Coffcer/vu... </p><p><strong>其他的优化点</strong></p><p>除了组件上的优化,我们还可以对vue的依赖改造入手。初始化时,vue会对data做getter、setter改造,在现代浏览器里,这个过程实际上挺快的,但仍然有优化空间。</p><p><code>Object.freeze()</code>是ES5新增的API,用来冻结一个对象,禁止对象被修改。vue 1.0.18+以后,不会对已冻结的data做getter、setter转换。</p><p>如果你确保某个data不需要跟踪依赖,可以使用Object.freeze将其冻结。但请注意,被冻结的是对象的值,你仍然可以将引用整个替换调。看下面例子:</p><div><pre><p v-for="item in list">{{ item.value }}</p></pre></div><div><pre>new Vue({ data: { // vue不会对list里的object做getter、setter绑定 list: Object.freeze([ { value: 1 }, { value: 2 } ]) }, created () { // 界面不会有响应 this.list[0].value = 100; // 下面两种做法,界面都会响应 this.list = [ { value: 100 }, { value: 200 } ]; this.list = Object.freeze([ { value: 100 }, { value: 200 } ]); } }) </pre></div><p><strong>后记</strong></p><p>vue 1.0+ 的组件其实不算轻量,初始化一个组件包括依赖收集、转换等过程,但其实有些是可以放在编译时提前完成的。vue 2.0+ 已经在这方面做了不少的改进:分离了编译时和运行时、提供函数组件等,可以预见,vue 2.0的性能将有很大的提升。</p><p>v-lazy-component: https://github.com/Coffcer/vu...  </p><p>以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持创新互联。</p> <br> 分享文章:浅谈Vue初始化性能优化 <br> 文章转载:<a href="http://xwwzsj.com/article/psoocp.html">http://xwwzsj.com/article/psoocp.html</a> </div> </div> <div class="other"> <h3>其他资讯</h3> <ul> <li> <a href="/article/eecgdg.html">鞍山短视频运营代理</a> </li><li> <a href="/article/eecipc.html">杭州短视频运营创业</a> </li><li> <a href="/article/eecigp.html">探店搞笑名称大全抖音必看涨姿势啦~</a> </li><li> <a href="/article/eecipj.html">昭通短视频营销,昭通短视频营销</a> </li><li> <a href="/article/eecigs.html">大理短视频运营机构哪家好</a> </li> </ul> </div> </div> <div class="f_service_con"> <div class="h_fumin"> <div class="h_fumin_lei"> <div class="h_fumin_lei_tu"><img src="/Public/Home/images/f_service01.png"></div> <p>售后响应及时</p><span>7×24小时客服热线</span> </div> <div class="h_fumin_lei"> <div class="h_fumin_lei_tu"><img src="/Public/Home/images/f_service02.png"></div> <p>数据备份</p><span>更安全、更高效、更稳定</span> </div> <div class="h_fumin_lei"> <div class="h_fumin_lei_tu"><img src="/Public/Home/images/f_service03.png"></div> <p>价格公道精准</p><span>项目经理精准报价不弄虚作假</span> </div> <div class="h_fumin_lei"> <div class="h_fumin_lei_tu"><img src="/Public/Home/images/f_service04.png"></div> <p>合作无风险</p><span>重合同讲信誉,无效全额退款</span> </div> </div> </div> <div class="footerbar"> <div class="footer-t"> <div class="f-box"> <div class="f-1"> <div class="f-t"> <h2>联系我们</h2> <span>TEL</span> </div> <div class="f-b"> <h1><a href="tel:13518219792" rel="nofollow">135-1821-9792</a></h1> <h1><a href="tel:028-86922220" rel="nofollow">028-86922220</a></h1> <p>地址:成都市太升南路288号锦天国际</p> </div> </div> <div class="f-2"> <div class="f-t"> <h2>快捷导航</h2> <span>Shortcut</span> </div> <div class="f-b"> <ul > </ul> <ul > <li><a href="/jianshe" title="宣威网站建设">宣威网站建设</a></li> <li><a href="/jianshe#ym_websiteBox2" title="品牌网站建设">品牌网站建设</a></li> <li><a href="/jianshe#ym_websiteBox1" title="企业网站建设">企业网站建设</a></li> <li><a href="/jianshe#ym_websiteBox4" title="集团网站建设">集团网站建设</a></li> <li><a href="/jianshe#ym_websiteBox4_2" title="外贸网站建设">外贸网站建设</a></li> <li><a href="/jianshe#ym_websiteBox4_5" title="企业宣传视频">企业宣传视频</a></li> </ul> <ul > <li><a href="/weixin" title="微信开发">微信开发</a></li> <li><a href="/weixin#item1" title="公众号开发">公众号开发</a></li> <li><a href="/weixin#item2" title="微商城建设">微商城建设</a></li> <li><a href="/weixin#item3" title="微官网建设">微官网建设</a></li> <li><a href="/weixin#item4" title="小程序开发">小程序开发</a></li> </ul> <ul> <li><a href="/case/" title="网站作品案例">网站作品案例</a></li> <li><a href="/case/" title="品牌网站案例">品牌网站案例</a></li> <li><a href="/case/" title="集团网站案例">集团网站案例</a></li> <li><a href="/case/" title="企业网站案例">企业网站案例</a></li> <li><a href="/case/" title="外贸网站案例">外贸网站案例</a></li> <li><a href="/case/" title="营销网站案例">营销网站案例</a></li> </ul> <ul style="margin:0;"> <li><a href="/about/">瑞达杰昌建站</a></li> <li><a href="/about/">公司简介</a></li> <li><a href="/about#ab_item3">企业文化</a></li> <li><a href="/contact">联系我们</a></li> <li><a href="/Pay.html">付款方式</a></li> <li><a href="/jianshe#ym_websiteBox8">售后服务</a></li> </ul> <div style="clear:both;"></div> </div> </div> <div class="f-3"> <div class="f-t"> <h2>二维码</h2> <span>QR CODE</span> </div> <div class="f-b"> <ul> <li><img src="/Public/Home/images/fewm.png"> <p>微信公众号</p> </li> <li style="margin: 0"><img src="/Public/Home/images/fewm2.png"> <p>手机端网站</p> </li> <div style="clear:both;"></div> </ul> </div> </div> <div style="clear:both;"></div> </div> </div> <div class="footer-about"> <div class="w1200">瑞达杰昌建站工作室是一家专注从事于高品质视觉体验及互联网设计开发,<a href="/" target="_blank">宣威网站建设</a>,<a href="/jianshe" target="_blank">宣威网站设计</a>,<a href="/jianshe" target="_blank">宣威网页设计</a>,<a href="/jianshe" target="_blank">宣威网站制作</a>,<a href="/jianshe#ym_websiteBox2" target="_blank">品牌网站建设</a>,<a href="/jianshe#ym_websiteBox3" target="_blank">营销网站建设</a>,<a href="/jianshe#ym_websiteBox4" target="_blank">集团网站建设</a>,<a href="/jianshe#ym_websiteBox1" target="_blank">企业网站建设</a>,<a href="/jianshe#ym_websiteBox4_2" target="_blank">外贸网站建设</a>,<a href="/jianshe#ym_websiteBox4_3" target="_blank">响应式网站建设</a>,<a href="/weixin#item4" target="_blank">小程序开发</a>,<a href="/weixin" target="_blank">微信开发</a>,<a href="/jianshe#ym_websiteBox4_4" target="_blank">企业形象设计</a>,<a href="/jianshe#ym_websiteBox4_5" target="_blank">企业宣传视频</a>等服务,瑞达杰昌建站位于宣威市龙岗区大运软件小镇,瑞达杰昌建站拥有经验丰富的高级网站建设工程师和一流的网页高端设计人员,具备各种规模与类型网站建设的雄厚实力,在网站建设领域树立了自己独特的设计风格。 </div> <div class="friend-links"> <h6 class="clearfix"> <span class="tilte">友情链接</span> <a class="exchagne" href="http://wpa.qq.com/msgrd?v=3&uin=631063699&site=qq&menu=yes">交换友情链接</a> </h6> <div class="link-list clearfix"> <div class="link-slider"> <a href="https://www.cdcxhl.com/gaiban/" title="网站改版" target="_blank">网站改版</a>   <a href="http://www.tpyxedu.com/" title="公司形象墙" target="_blank">公司形象墙</a>   <a href="http://www.dwdengju.com/" title="大悟县护眼台灯销售" target="_blank">大悟县护眼台灯销售</a>   <a href="http://www.scxuyong.com/" title="叙永做网站" target="_blank">叙永做网站</a>   <a href="http://www.slowang.com/" title="成都石笼网公司" target="_blank">成都石笼网公司</a>   <a href="https://www.cdcxhl.com/h5.html" title="成都h5网站建设" target="_blank">成都h5网站建设</a>   <a href="http://www.cxjianzhan.com/" title="网站推广" target="_blank">网站推广</a>   <a href="http://www.cdkmsfdj.com/" title="成都康明斯发电机公司" target="_blank">成都康明斯发电机公司</a>   <a href="http://chengdu.cdcxhl.cn/qiye/" title="成都企业网站建设公司" target="_blank">成都企业网站建设公司</a>   <a href="https://www.cdxwcx.com/jifang/wenjiang.html" title="成都多线机房" target="_blank">成都多线机房</a>    </div> </div> </div> </div> <div class="footer-b"> <div class="f-box"> <ul> <li><a href="/jianshe#ym_websiteBox6" target="_blank">服务流程</a></li> <li><a href="/jianshe#ym_websiteBox8" target="_blank">售后服务</a></li> <li><a href="/about/" target="_blank">联系我们</a></li> <li><a href="https://www.cdxwcx.com/pay/" target="_blank">付款方式</a></li> <li><a href="https://www.cdcxhl.com/menu.html" target="_blank">网站地图</a></li> <li><a href="#" target="_blank">sitemap</a></li> <li> <p> <script data-cfasync="false" src="/Public/Home/js/email-decode.min.js"></script> </p> </li> <div style="clear:both;"></div> </ul> <p class="copy">Copyright © 2025 青羊区瑞达杰昌互联网信息服务工作室(个体工商户) 宣威建站 All Rights Reserved   <a href="https://beian.miit.gov.cn/" target="_blank" rel="nofollow">蜀ICP备2025133229号-6</a> <a style="display:none" target="_blank" href="###"><img style="vertical-align:middle" border="0" src="" width="65" height="25" /></a> </p> <div style="clear:both;"></div> </div> </div> <div class="sj_footer"> <div class="f-box"> <ul> <li><a href="/jianshe" target="_blank">网站建设</a></li> <li><a href="/jianshe#ym_websiteBox6" target="_blank">服务流程</a></li> <li><a href="/jianshe#ym_websiteBox8" target="_blank">售后服务</a></li> <li><a href="https://www.cdxwcx.com/pay/" target="_blank">付款方式</a></li> <li><a href="/about/" target="_blank">关于我们</a></li> <li><a href="https://www.cdcxhl.com/menu.html" target="_blank">网站地图</a></li> <div style="clear:both;"></div> </ul> <p class="copy">Copyright © 2025 青羊区瑞达杰昌互联网信息服务工作室(个体工商户) 宣威建站</p> <p class="copy"> <a href="https://beian.miit.gov.cn/" target="_blank" rel="nofollow">蜀ICP备2025133229号-6</a>  <a href="###" target="_blank"><img src="/Public/Home/images/govicon.gif" width="20" height="28" border="0" style="border-width:0px;border:hidden; border:none;"></a></p> <div style="clear:both;"></div> </div> </div> </div> <script type='text/javascript' src='/Public/Home/js/qqkefu.js'></script> <div class="qqkefu"> <ul> <li class="qq_czaa" id="130"><b class="a"></b>135-1821-9792</li> <li class="qq_czaa" id="130"><a href="tencent://message/?uin=1683211881"><b class="b"></b>业务咨询QQ</a></li> <li class="qq_czaa" id="130"><a href="javascript:showDiv()"><b class="f"></b>提交合作意向表</a></li> <li class="qq_czb"> <b class="c"></b> <div class="erweima"> <p><img src="/Public/Home/images/right_erweima.png"></p> </div> </li> <li class="top"><span></span></li> </ul> </div> <div id="popDiv" class="mydiv" style="display:none;"> <a class="mydiv_clk" href="javascript:closeDiv()">X</a> <div class="mydiv_list"> <div class="c_f_title"><span class="c_f_t">合作意向表</span></div> <div class="c_f_con"> <form id="form1" name="form1" class="mess_form" method="post" action="/post_order"> <input name='enews' type='hidden' value='AddFeedback'> <input name="bid" value="1" type="hidden"> <input type="hidden" name="ecmsfrom" value="9"> <input type="hidden" name='title' value="客户提交需求"> <li class="c_n"><span>公司名称</span> <dl><input name='gsname' id='gsname' type="text"></dl> </li> <li class="c_n"><span>邮箱</span> <dl><input name='gemail' id='gemail' type="text"></dl> </li> <li class="c_n xmm"> <div class="xmm_01"><span>姓名</span> <dl class="c_n_i"><input name='name' id='name' type="text"></dl> </div> <div class="xmm_01"><span style="text-align:center">电话</span> <dl class="c_n_i"><input name="tel" type="text"></dl> </div> </li> <li class="c_tser">您需要的服务</li> <li class="clearfix"> <dd><label><input type="radio" name='hobby' id='hobby' value="高端网站建设"><span>高端网站建设</span></label></dd> <dd><label><input type="radio" name='hobby' id='hobby' value="我需要做微信营销"><span>我需要做微信营销</span></label></dd> <dd><label><input type="radio" name='hobby' id='hobby' value="要找长期合作,需要年度服务"><span>要找长期合作,需要年度服务</span></label></dd> <dd><label><input type="radio" name='hobby' id='hobby' value="我需要做购物商城"><span>我需要做购物商城</span></label></dd> <dd><label><input type="radio" name='hobby' id='hobby' value="我需要网站改版"><span>我需要网站改版</span></label></dd> <dd><label><input type="radio" name='hobby' id='hobby' value="其他"><span>其他</span></label></dd> </li> <li class="c_tser">您关注的地方</li> <li class="clearfix"> <dd><label><input type="radio" name='hobby2' id='hobby2' value="对功能要求比较高"><span>对功能要求比较高</span></label></dd> <dd><label><input type="radio" name='hobby2' id='hobby2' value="对设计创意要求比较高"><span>对设计创意要求比较高</span></label></dd> <dd><label><input type="radio" name='hobby2' id='hobby2' value="需要可以购物支付"><span>需要可以购物支付</span></label></dd> <dd><label><input type="radio" name='hobby2' id='hobby2' value="搜索引擎排名"><span>搜索引擎排名</span></label></dd> </li> <li class="c_tser">预算</li> <li class="clearfix clearfix2"> <dd><label><input type="radio" name='hobby3' id='hobby3' value="一万以内"><span>一万以内</span></label> </dd> <dd><label><input type="radio" name='hobby3' id='hobby3' value="1-3万"><span>1-3万</span></label> </dd> <dd><label><input type="radio" name='hobby3' id='hobby3' value="3-5万"><span>3-5万</span></label> </dd> <dd><label><input type="radio" name='hobby3' id='hobby3' value="5万以上"><span>5万以上</span></label> </dd> <dd><label><input type="radio" name='hobby3' id='hobby3' value="需招投标"><span>需招投标</span></label> </dd> </li> <li class="c_n" style="border-top:1px solid #eee; padding-top:10px"><span>验证码</span> <dl class="c_n_i yzmm"><input type="text" name='code' id='code' value=""></dl><span style="text-align:center"><img src="/Public/Home/images/1661eb19783442c38063791555cd0d80.gif" onclick="this.src=this.src + '?'" width="100" height="40"></span> </li> <li class="clearfix"> <dd class="submit"><input name='submit' type="submit" value="提交需求"></dd> </li> </form> </div> </div> </div> <div id="bg" class="bg" style="display:none;"></div> <div id='popIframe' class='popIframe' frameborder='0'></div> <script> //提交需求选项 $(document).ready(function (e) { $(".mess_form").submit(function () { if ($("#gsname").val() == "") { alert("请填写您的公司名称!"); $("#gsname").focus(); return false; } if ($("#gemail").val() == "") { alert("请填写您的邮箱"); $("#gemail").focus(); return false; } if ($("#name").val() == "") { alert("请填写您的姓名!"); $("#name").focus(); return false; } if ($("#tel").val() == "") { alert("请填写您的电话!"); $("#tel").focus(); return false; } if ($("#hobby").val() == "") { alert("请选择您需要的服务!"); $("#hobby").focus(); return false; } if ($("#hobby2").val() == "") { alert("请选择您关注的地方!"); $("#hobby2").focus(); return false; } if ($("#hobby3").val() == "") { alert("请选择您的预算!"); $("#hobby3").focus(); return false; } if ($("#code").val() == "") { alert("请填写正确的验证码!"); $("#code").focus(); return false; } }); }); </script> <script language="javascript" type="text/javascript"> //提交需求窗口 function showDiv() { document.getElementById('popDiv').style.display = 'block'; document.getElementById('popIframe').style.display = 'block'; document.getElementById('bg').style.display = 'block'; } function closeDiv() { document.getElementById('popDiv').style.display = 'none'; document.getElementById('bg').style.display = 'none'; document.getElementById('popIframe').style.display = 'none'; } </script> <script type="text/javascript" src="/Public/Home/js/scrolltopcontrol.js"></script> <script type="text/javascript" src="/Public/Home/js/su_new.js"></script> </body> </html> <script> $(".con img").each(function(){ var src = $(this).attr("src"); //获取图片地址 var str=new RegExp("http"); var result=str.test(src); if(result==false){ var url = "https://www.cdcxhl.com"+src; //绝对路径 $(this).attr("src",url); } }); window.onload=function(){ document.oncontextmenu=function(){ return false; } } </script>