全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

浅谈Vue 初始化性能优化

前言

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

性能瓶颈在哪里?

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

<body>
  <app></app> 
</body>

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

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

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

第一种:不使用根组件

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

<body>
  <A></A>
  <B></B>
  <C></C>
</body>

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

第二种:异步组件

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

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

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

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

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

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 )
  }
})

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

<app>
  <title></title>
  <A></A>
  <title></title>
  <B></B>
  <title></title>
  <C></C>
</app>

还是按照上面的异步组件做法,这时候就需要考虑把哪些组件设成异步的了。如果把A、B、C都设成异步的,那结果就是3个<title>会首先渲染出来,页面渲染的过程在用户看来非常奇怪,并不是预期中的从上到下顺序渲染。

第三种:v-if 和 terminal指令

这是我推荐的一种做法,简单有效。还是那个结构,我们给要延迟渲染的组件加上v-if:

<app>
  <A></A>
  <B v-if="showB"></B>
  <C v-if="showC"></C>
</app>
new Vue({
  data: {
    showB: false,
    showC: false
  },
  created () {
    // 显示B
    setTimeout(() => {
      this.showB = true;
    }, 0);
    // 显示C
    setTimeout(() => {
      this.showC = true;
    }, 0);
  }
});

这个示例写起来略显啰嗦,但它已经实现了我们想要的顺序渲染的效果。页面会在A组件初始化完后显示,然后再按顺序渲染其余的组件,整个页面渲染方式看起来是流式的。

有些人可能会担心v-if存在一个编译/卸载过程,会有性能影响。但这里并不需要担心,因为v-if是惰性的,只有当第一次值为true时才会开始初始化。

这种写法看起来很麻烦,如果我们能实现一个类似v-if的组件,然后直接指定多少秒后渲染,那就更好了,例如:

<app>
  <A></A>
  <B v-lazy="0"></B>
  <C v-lazy="100"></C>
</app>

一个简单的指令即可,不需要js端任何配合,并且可以用在普通dom上面,Nice!

在vue里,类似v-if和v-for这种是terminal指令,会在指令内部编译组件。如果你想要自己实现一个terminal指令,需要加上terminal: true,例如:

Vue.directive('lazy', {
  terminal: true,
  bind () {},
  update () {},
  unbind () {}
});

这是vue在1.0.19+新增的功能,由于比较冷门,文档也没有特别详细的叙述,最好的方式是参照着v-if和v-for的源码来写。

我已经为此封装了一个terminal指令,你可以直接使用:https://github.com/Coffcer/vu... 

其他的优化点

除了组件上的优化,我们还可以对vue的依赖改造入手。初始化时,vue会对data做getter、setter改造,在现代浏览器里,这个过程实际上挺快的,但仍然有优化空间。

Object.freeze()是ES5新增的API,用来冻结一个对象,禁止对象被修改。vue 1.0.18+以后,不会对已冻结的data做getter、setter转换。

如果你确保某个data不需要跟踪依赖,可以使用Object.freeze将其冻结。但请注意,被冻结的是对象的值,你仍然可以将引用整个替换调。看下面例子:

<p v-for="item in list">{{ item.value }}</p>
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 }
    ]);
  }
})

后记

vue 1.0+ 的组件其实不算轻量,初始化一个组件包括依赖收集、转换等过程,但其实有些是可以放在编译时提前完成的。vue 2.0+ 已经在这方面做了不少的改进:分离了编译时和运行时、提供函数组件等,可以预见,vue 2.0的性能将有很大的提升。

v-lazy-component: https://github.com/Coffcer/vu... 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# Vue  # 初始化性能优化  # 初始化性能  # 浅谈Vue 性能优化之深挖数组  # Vue性能优化的方法  # Vue.js性能优化N个技巧(值得收藏)  # 分享12个Vue开发中的性能优化小技巧(实用!)  # 会在  # 会有  # 会对  # 放在  # 你可以  # 不需要  # 其他的  # 时才  # 完后  # 自己的  # 的是  # 从上到下  # 是一个  # 这是  # 流式  # 文档  # 如果你  # 也有  # 我在  # 最好的 


相关文章: 如何获取开源自助建站系统免费下载链接?  家具网站制作软件,家具厂怎么跑业务?  微信h5制作网站有哪些,免费微信H5页面制作工具?  建站之星如何快速更换网站模板?  装修招标网站设计制作流程,装修招标流程?  浅析上传头像示例及其注意事项  如何通过云梦建站系统实现SEO快速优化?  如何通过虚拟主机快速搭建个人网站?  如何基于云服务器快速搭建网站及云盘系统?  宁波免费建站如何选择可靠模板与平台?  建站主机选虚拟主机还是云服务器更好?  电商平台网站制作流程,电商网站如何制作?  网站视频怎么制作,哪个网站可以免费收看好莱坞经典大片?  如何通过虚拟主机空间快速建站?  如何在Mac上搭建Golang开发环境_使用Homebrew安装和管理Go版本  建站org新手必看:2024最新搭建流程与模板选择技巧  如何在Ubuntu系统下快速搭建WordPress个人网站?  建站之星后台密码遗忘如何找回?  ui设计制作网站有哪些,手机UI设计网址吗?  ,交易猫的商品怎么发布到网站上去?  制作网站的模板软件,网站怎么建设?  宁波自助建站系统如何快速打造专业企业网站?  东莞市网站制作公司有哪些,东莞找工作用什么网站好?  西安大型网站制作公司,西安招聘网站最好的是哪个?  如何通过免费商城建站系统源码自定义网站主题与功能?  *服务器网站为何频现安全漏洞?  外贸公司网站制作,外贸网站建设一般有哪些步骤?  如何在景安云服务器上绑定域名并配置虚拟主机?  大连 网站制作,大连天途有线官网?  如何在西部数码注册域名并快速搭建网站?  如何在宝塔面板中修改默认建站目录?  制作网站怎么制作,*游戏网站怎么搭建?  网站制作壁纸教程视频,电脑壁纸网站?  在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?  如何通过IIS搭建网站并配置访问权限?  网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?  长沙企业网站制作哪家好,长沙水业集团官方网站?  制作网站的基本流程,设计网站的软件是什么?  如何用狗爹虚拟主机快速搭建网站?  如何选择适配移动端的WAP自助建站平台?  如何快速生成ASP一键建站模板并优化安全性?  建站ABC备案流程中有哪些关键注意事项?  建站之星在线版空间:自助建站+智能模板一键生成方案  如何通过宝塔面板实现本地网站访问?  建站之星如何通过成品分离优化网站效率?  如何通过服务器快速搭建网站?完整步骤解析  最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?  免费制作海报的网站,哪位做平面的朋友告诉我用什么软件做海报比较好?ps还是cd还是ai这几个软件我都会些我是做网页的?  哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?  枣阳网站制作,阳新火车站打的到仙岛湖多少钱? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。