使用异步组件优化Vue应用程序的性能


Posted in Javascript onApril 28, 2019

单页应用其一个问题是首屏屏渲染速度较慢。这是因为页面首次加载时服务器将向客户端发送大量JavaScript,在屏幕上显示任何内容之前必须下载并解析。可以想象,随着应用程序规模的扩大,这个问题对用户体验的影响也会越来越突出。

现在幸运的是,当使用Vue CLI构建Vue应用程序时(使用webpack),可以采取一些措施来抵消这种情况。在本文中,我将演示如何在应用程序的初始渲染之后使用 异步组件 和webpack的代码分割功能加载到页面的某些部分。这将使初始加载时间降至最低,并为您的应用程序提供更好的用户体验。

认识异步组件

在我们开始创建异步组件之前,让我们看一下我们通常如何加载组件。为此,我们将使用一个非常简单的消息组件作为例子:

<!-- Message.vue -->
<template>
 <h1>New message!</h1>
</template>

现在我们已经创建了我们的 Message 组件,让我们将它加载到我们的文件中并显示它。我们可以导入组件并将其添加到组件选项中,以便我们可以在模板中使用它:

<!-- App.vue -->
<template>
 <div>
 <message></message>
 </div>
</template>

<script>
import Message from "./Message";
export default {
 components: {
 Message
 }
};
</script>

但现在发生了什么?只要应用程序加载,就会加载 Message 组件,因此它包含在初始加载过程中。

对于一个简单的应用程序来说,这看起来可能不是一个大问题,但可以考虑像电商网站这样复杂的场景。想象一下,用户将项目添加到购物车,然后想要结帐,因此单击结帐按钮会生成一个包含所选商品的所有详细信息的框。使用上述方法,此结帐框将包含在初始包中,但我们只需在用户单击结帐按钮时使用该组件。用户甚至可以在不点击结账按钮的情况下浏览网站,这意味着在加载这个可能不会使用的组件时浪费资源是没有意义的。

为了提高应用程序的效率,我们可以结合延迟加载和代码分割技术。

Webpack提供的代码拆分功能允许您将代码拆分为各种捆绑包,然后可以按需加载或稍后并行加载。它只能在需要或使用时加载特定的代码片段。

Dynamic Imports(动态导入)

Vue使用Dynamic Imports解决这种情况。此功能引入了一种新的类似函数的导入形式,它将返回包含(Vue)组件的Promise。由于import是一个接收字符串的函数,我们可以做一些强大的事情,比如使用表达式加载模块。自版本61以来,Chrome中已提供动态导入。有关这些内容的详细信息, 请访问Google Developers网站 。

代码拆分由webpack,Rollup或Parcel等捆绑器处理,它们解析动态导入语法并为每个动态导入的模块创建单独的文件。稍后我们将在控制台的网络选项卡中看到这一点。但首先,我们来看看静态和动态导入之间的区别:

// static import
import Message from "./Message";

// dynamic import
import("./Message").then(Message => {
 // Message module is available here...
});

现在,让我们将这些知识应用到我们的 Message 组件中,我们将得到一个如下所示的组件: App.vue

<!-- App.vue -->
<template>
 <div>
 <message></message>
 </div>
</template>

<script>
import Message from "./Message";
export default {
 components: {
 Message: () => import("./Message")
 }
};
</script>

如你所见,函数import()将解析返回组件的Promise,这意味着我们已成功异步加载组件。如果您查看 devtoolsnetwork 选项卡,您会注意到一个名为 0.js 包含异步组件的文件。

使用异步组件优化Vue应用程序的性能 

根据条件加载异步组件

现在我们已经掌握了异步组件,让我们仅在真正需要时加载它们。在本文的上一节中,我解释了仅在用户点击结帐按钮时才加载的结帐框的用例。让我们把它构建出来。

项目设置

如果您没有安装 vue/cli ,首先应该安装它:

npm i -g @vue/cli

接下来,使用CLI创建新项目,在出现提示时选择默认预设即可:

vue create my-store

转到项目目录,然后安装我们将用于样式的ant-design-vue库:

cd my-store
npm i ant-design-vue

接下来,导入Ant设计库: src/main.js

import 'ant-design-vue/dist/antd.css'

最后我们在 src/comonents 里创建两个新组件 Checkout.vueItems.vue

touch src/components/{Checkout.vue,Items.vue}

写一个商店的视图层

打开 src/App.vue 并用以下代码替换文件里代码:

<template>
 <div id="app">
 <h1>{{ msg }}</h1>
 <items></items>
 </div>
</template>

<script>
import items from "./components/Items"

export default {
 components: {
 items
 },
 name: 'app',
 data () {
 return {
  msg: 'My Fancy T-Shirt Store'
 }
 }
}
</script>

<style>
#app {
 font-family: 'Avenir', Helvetica, Arial, sans-serif;
 -webkit-font-smoothing: antialiased;
 -moz-osx-font-smoothing: grayscale;
 text-align: center;
 color: #2c3e50;
 margin-top: 60px;
}

h1, h2 {
 font-weight: normal;
}

ul {
 list-style-type: none;
 padding: 0;
}

li {
 display: inline-block;
 margin: 0 10px;
}

a {
 color: #42b983;
}
</style>

这里没有什么花哨的东西。我们所做的只是显示一条消息并渲染一个 <items> 组件。

接下来,打开 src/components/Items.vue 并添加以下代码:

<template>
 <div>
 <div style="padding: 20px;">
  <Row :gutter="16">
  <Col :span="24" style="padding:5px">
   <Icon type="shopping-cart" style="margin-right:5px"/>{{shoppingList.length}} item(s)
   <Button @click="show = true" id="checkout">Checkout</Button>
  </Col>
  </Row>
 </div>
 <div v-if="show">
  <Row :gutter="16" style="margin:0 400px 50px 400px">
  <checkout v-bind:shoppingList="shoppingList"></checkout>
  </Row>
 </div>
 <div style="background-color: #ececec; padding: 20px;">
  <Row :gutter="16">
  <Col :span="6" v-for="(item, key) in items" v-bind:key="key" style="padding:5px">
   <Card v-bind:title="item.msg" v-bind:key="key">
   <Button type="primary" @click="addItem(key)">Buy ${{item.price}}</Button>
   </Card>
  </Col>
  </Row>
 </div>
 </div>
</template>

<script>
import { Card, Col, Row, Button, Icon } from 'ant-design-vue';

export default {
 methods: {
 addItem (key) {
  if(!this.shoppingList.includes(key)) {
  this.shoppingList.push(key);
  }
 }
 },
 components: {
 Card, Col, Row, Button, Icon,
 checkout: () => import('./Checkout')
 },
 data: () => ({
 items: [
  { msg: 'First Product', price: 9.99 },
  { msg: 'Second Product', price: 19.99 },
  { msg: 'Third Product', price: 15.00 },
  { msg: 'Fancy Shirt', price: 137.00 },
  { msg: 'More Fancy', price: 109.99 },
  { msg: 'Extreme', price: 3.00 },
  { msg: 'Super Shirt', price: 109.99 },
  { msg: 'Epic Shirt', price: 3.00 },
 ],
 shoppingList: [],
 show: false
 })
}
</script>
<style>
#checkout {
 background-color:#e55242;
 color:white;
 margin-left: 10px;
}
</style>

在此文件中,我们显示一个带有商品数量的购物车图标。商品是从 items 数组中提取的。如果单击项目的 Buy 按钮,将会调用 addItem 方法,该方法会将相关商品push到 shoppingList 数组中。从而增加购物车的总数。

我们还在页面中添加了一个 Checkout 按钮:

<Button @click="show = true" id="checkout">Checkout</Button>

当用户点击这个按钮,我们设置的参数 showtruetrue 是非常重要对于有通过条件地加载我们的异步组件。

在接下来的几行中,您可以找到 v-if 的声明,这个语句仅用来显示我们 checkout 组件的 <div> ,但是我们只想在用户点击 Checkout 按钮时显示结账组件,我们该怎么办?

这里我们将 checkout 组件在 components 选项里异步加载。这里 v-bind 将参数传递给组件。正如你看的的这样,创建条件异步组件是很容易的:

<div v-if="show">
 <checkout v-bind:shoppingList="shoppingList"></checkout>
</div>

让我们快速 Checkout 组件添加下面的代码在 src/components/Checkout.vue 里:

<template>
 <Card title="Checkout Items" key="checkout">
 <p v-for="(k, i) in this.shoppingList" :key="i">
  Item: {{items[Number(k)].msg}} for ${{items[Number(k)].price}}
 </p>
 </Card>
</template>

<script>
import { Card } from 'ant-design-vue';

export default {
 props: ['shoppingList'],
 components: {
 Card
 },
 data: () => ({
 items: [
  { msg: 'First Product', price: 9.99 },
  { msg: 'Second Product', price: 19.99 },
  { msg: 'Third Product', price: 15.00 },
  { msg: 'Fancy Shirt', price: 137.00 },
  { msg: 'More Fancy', price: 109.99 },
  { msg: 'Extreme', price: 3.00 },
  { msg: 'Super Shirt', price: 109.99 },
  { msg: 'Epic Shirt', price: 3.00 },
 ]
 })
}
</script>

在这里,我们将接收一个 shoppingList 并把他输出到屏幕上。

您可以使用该 npm run serve 命令运行该应用程序。然后导航到 http:// localhost:8080 。如果一切按计划进行,你应该会看到如下图所示的内容。

使用异步组件优化Vue应用程序的性能

可以尝试打开在 network 选项卡,点击Checkout按钮,可以发现 network 里将异步加载 结账组件

您还可以在GitHub上查看此演示的代码 。

为异步组件添加加载中和加载错误组件

有时异步组件加载过长或加载时。显示加载动画或错误信息可能很有用,但要支持这会再次降低应用程序的速度。异步组件应该小而且加载速度快。这是一个例子:

const Message = () => ({
 component: import("./Message"),
 loading: LoadingAnimation,
 error: ErrorComponent
});

总结

创建和实现异步组件非常简单,应该成为标准开发例程的一部分。从用户体验的角度来看,尽可能减少初始加载时间以保持用户的注意力是非常重要。希望本教程可以帮助您构建异步加载组件。

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

Javascript 相关文章推荐
js利用Array.splice实现Array的insert/remove
Jan 13 Javascript
详解jquery uploadify 上传文件
Nov 09 Javascript
如何获取网站icon有哪些可行的方法
Jun 05 Javascript
关于JS数组追加数组采用push.apply的问题
Jun 09 Javascript
jQuery+PHP+MySQL二级联动下拉菜单实例讲解
Oct 27 Javascript
jquery单击事件和双击事件冲突解决方案
Mar 02 Javascript
jQuery获取单击节点对象的方法
Jun 02 Javascript
jquery实现跳到底部,回到顶部效果的简单实例(类似锚)
Jul 10 Javascript
JQuery遍历元素的后代和同胞实现方法
Sep 18 Javascript
微信小程序实战之自定义toast(6)
Apr 18 Javascript
AngularJS实现表单验证功能详解
Oct 12 Javascript
微信小程序判断页面是否从其他页面返回的实例代码
Jul 03 Javascript
详解微信小程序获取当前时间及日期的方法
Apr 28 #Javascript
vue自定义js图片碎片轮播图切换效果的实现代码
Apr 28 #Javascript
如何在微信小程序里面退出小程序的方法
Apr 28 #Javascript
vue实现移动端轻量日期组件不依赖第三方库的方法
Apr 28 #Javascript
详解小程序退出页面时清除定时器
Apr 28 #Javascript
详解在Javascript中进行面向切面编程
Apr 28 #Javascript
js比较两个单独的数组或对象是否相等的实例代码
Apr 28 #Javascript
You might like
在PHP中读取和写入WORD文档的代码
2008/04/09 PHP
PHP微框架Dispatch简介
2014/06/12 PHP
PHP使用递归按层级查找数据的方法
2019/11/10 PHP
Sample script that displays all of the users in a given SQL Server DB
2007/06/16 Javascript
关于javascript中的parseInt使用技巧
2009/09/03 Javascript
jQuery 操作option的实现代码
2011/03/03 Javascript
JavaScript禁止页面操作的示例代码
2013/12/17 Javascript
javascript实现数字+字母验证码的简单实例
2014/02/10 Javascript
jquery显示loading图片直到网页加载完成的方法
2015/06/25 Javascript
javascript实现无缝上下滚动特效
2015/12/16 Javascript
只需五句话搞定JavaScript作用域(经典)
2016/07/26 Javascript
javascript replace()第二个参数为函数时的参数用法
2016/12/26 Javascript
JS利用cookies设置每隔24小时弹出框
2017/04/20 Javascript
vue1.0和vue2.0的watch监听事件写法详解
2018/09/11 Javascript
vue页面切换过渡transition效果
2018/10/08 Javascript
javascript中join方法实例讲解
2019/02/21 Javascript
快速解决vue2+vue-cli3项目ie兼容的问题
2020/11/17 Vue.js
[02:34]肉山说——泡妞篇
2014/09/16 DOTA
Python利用QQ邮箱发送邮件的实现方法(分享)
2017/06/09 Python
Python实现桶排序与快速排序算法结合应用示例
2017/11/22 Python
详解Python中的四种队列
2018/05/21 Python
在Python文件中指定Python解释器的方法
2019/02/18 Python
Python queue队列原理与应用案例分析
2019/09/27 Python
Python 分布式缓存之Reids数据类型操作详解
2020/06/24 Python
Python基于xlutils修改表格内容过程解析
2020/07/28 Python
Django模型验证器介绍与源码分析
2020/09/08 Python
Pytorch之扩充tensor的操作
2021/03/04 Python
健康监测猫砂:Pretty Litter
2017/05/25 全球购物
毕业自我鉴定怎么写
2014/03/25 职场文书
员工激励培训演讲稿
2014/09/16 职场文书
群众路线个人对照检查材料
2014/09/23 职场文书
2014年群众路线党员自我评议
2014/09/24 职场文书
公司市场部岗位职责
2015/04/15 职场文书
建国大业观后感
2015/06/01 职场文书
浅谈redis缓存在项目中的使用
2021/05/20 Redis
Android Canvas绘制文字横纵向对齐
2022/06/05 Java/Android