Vue3 异步组件, 优化你的页面体验

295 阅读3分钟

其他Vue 系列文章

Vue 递归无限级菜单实现

随着时代的发展, 前端开发越来越火爆,组件开发也成为了潮流,用户体验也越来越重要。用户体验的第一要素就是性能了,如果一个页面要一二十秒才打开, 用户很有可能认为网站挂掉了,直接选择离开。今天介绍的Vue3异步组件正是解决这方面的其中一个方法。 在Vue3中要实现异步组件需要从vue 中引用 defineAsyncComponent

import { defineAsyncComponent } from 'vue'

今天就以一个Tab 切换功能来介绍defineAsyncComponent 的使用

先来看一个普通的写法,主页面代码如下

<template>

  <div class="book-content">
    <div class="tab">
      <span @click="setTab(1)" :class="{ active: activeTab === 1}">Js</span>
      <span @click="setTab(2)" :class="{ active: activeTab === 2}">Vue</span>
      <span @click="setTab(3)" :class="{ active: activeTab === 3}">React</span>
    </div>
    <div class="tab-content">
      <component :is="comName"></component>
    </div>
  </div>
</template>
<script setup>
import { ref, computed,  defineAsyncComponent } from 'vue'
import JsBook from '@/components/book/JsBook.vue'
import VueBook from '@/components/book/VueBook.vue'
import ReactBook from '@/components/book/ReactBook.vue'

const comConfig = {
1: JsBook,
2: VueBook,
3: ReactBook
}
const activeTab = ref(1)
const comName = computed(() => {
return comConfig\[activeTab.value]
})

function setTab (curr) {
activeTab.value = curr
} </script>

<style>
.tab {
  display: flex;
  width: 500px;
  justify-content: space-between;
  margin-bottom: 20px;
}
.tab span {
  width: 100px;
  height: 36px;
  line-height: 36px;
  border: 1px solid #ddd;
  border-radius: 5px;
  text-align: center;
  cursor: pointer;
}
.tab span.active{
  background: #4f8dff;
  color: #fff;
}
.tab-content {
  width: 500px;
  display: flex;
  justify-content: center;
}
.tab-content img {
  width: 200px;
}
</style>

JsBook.vue 代码如下:

<template>

  <div class="book-content">
    <img src="转存失败,建议直接上传图片文件 @/assets/images/javasript.jpg" alt="转存失败,建议直接上传图片文件">
    <h3>JavaSctipt Book</h3>
  </div>

<script setup="">
</script>

VueBook.vue 组件代码如下:

<template>

  <div class="book-content">
    <img src="转存失败,建议直接上传图片文件 @/assets/images/vue.webp" alt="转存失败,建议直接上传图片文件">
    <h3>Vue Book</h3>
  </div>

<script setup="">
</script>

ReactBook.vue 组件代码如下

<template>

  <div class="book-content">
    <img src="转存失败,建议直接上传图片文件 @/assets/images/react.webp" alt="转存失败,建议直接上传图片文件">
    <h3>React Book</h3>
  </div>

<script setup="">
</script> 

效果如下:

image.png

现在我们来看下 浏览器的network 请求,按ctrl + f5强制刷新下,

image.png 从上图可以看到,一开始就加载了所有的组件,但是一开始我们并不需要VueBook.vue组件,和ReactBook.vue组件,假如说这两个组件都是非常大的, 有几千行代码,那么是非常影响页面打开速度的,也就会影响用户体验。该怎么办呢? 现在defineAsyncComponent 就该出场了。

defineAsyncComponent的使用

<template>
  <div class="book-content">
    <div class="tab">
      <span @click="setTab(1)" :class="{ active: activeTab === 1}">Js</span>
      <span @click="setTab(2)" :class="{ active: activeTab === 2}">Vue</span>
      <span @click="setTab(3)" :class="{ active: activeTab === 3}">React</span>
    </div>
    <div class="tab-content">
      <component :is="comName"></component>
    </div>
  </div>
</template>
<script setup>
import { ref, computed,  defineAsyncComponent } from 'vue'
const JsBook = defineAsyncComponent(() => {
  return import('@/components/book/JsBook.vue')
})
const VueBook = defineAsyncComponent(() => {
  return import('@/components/book/VueBook.vue')
})
const ReactBook = defineAsyncComponent(() => {
  return import('@/components/book/ReactBook.vue')
})

const comConfig = {
  1: JsBook,
  2: VueBook,
  3: ReactBook
}
const activeTab = ref(1)
const comName = computed(() => {
  return comConfig[activeTab.value]
})

function setTab (curr) {
  activeTab.value = curr
}
</script>
<style>
.tab {
  display: flex;
  width: 500px;
  justify-content: space-between;
  margin-bottom: 20px;
}
.tab span {
  width: 100px;
  height: 36px;
  line-height: 36px;
  border: 1px solid #ddd;
  border-radius: 5px;
  text-align: center;
  cursor: pointer;
}
.tab span.active{
  background: #4f8dff;
  color: #fff;
}
.tab-content {
  width: 500px;
  display: flex;
  justify-content: center;
}
.tab-content img {
  width: 200px;
}
</style>

从上面的代码可以看到 defineAsyncComponent 接受一个函数作为参数,并且返回了一个import('组件的路径')

现在我们在开看下浏览器的network,ctrl + f5强制刷新

image.png

这时候你就会发现,只有JsBook.vue这个组件被加载了,而VueBook.vue组件和ReactBook.vue组件并没有被加载,这样我们就为页面初始化进行了一定的性能优化。 现在我们清除一下network请求,再来点击一下 Vue 选项 这个时候你会看见VueBook.vue组件被加载了,实现了按需加载

image.png

其他Vue 系列文章

Vue 递归无限级菜单实现