vue的动态组件和异步组件
一、动态组件
动态组件是使用 component 组件 ,通过一个特殊的attribute is 来实现 |
---|
下面通过一个例子去解释动态组件怎么用
如上图所示,比如我们现在想要实现了一个功能:点击一个tab-bar,切换不同的组件显示
这个案例我们可以通过三种不同的实现思路来实现
方式一
:通过v-if来判断,显示不同的组件方式二
:动态组件的方式方式三
:使用路由router-link和router-view
v-if显示不同的组件
<template>
<div>
<button
v-for="item in tabs"
:key="item"
@click="itemClick(item)"
:class="{active: currentTab === item}"
>{
{
item}}</button>
<!-- 1.v-if的判断实现 -->
<template v-if="currentTab === 'home'">
<home></home>
</template>
<template v-else-if="currentTab === 'about'">
<about></about>
</template>
<template v-else>
<category></category>
</template>
</div>
</template>
<script>
import Home from './pages/Home.vue';
import About from './pages/About.vue';
import Category from './pages/Category.vue';
export default {
components: {
Home,
About,
Category
},
data () {
return {
tabs: ["home", "about", "category"],
currentTab: "home"
}
},
methods: {
itemClick (item) {
this.currentTab = item;
}
}
}
</script>
<style scoped>
.active {
color: red;
}
</style>
动态组件的实现
<template>
<div>
<button
v-for="item in tabs"
:key="item"
@click="itemClick(item)"
:class="{active: currentTab === item}"
>{
{
item}}</button>
<!-- 2.动态组件 -->
<component :is="currentTab"></component>
</div>
</template>
<script>
import Home from './pages/Home.vue';
import About from './pages/About.vue';
import Category from './pages/Category.vue';
export default {
components: {
Home,
About,
Category
},
data () {
return {
tabs: ["home", "about", "category"],
currentTab: "home"
}
},
methods: {
itemClick (item) {
this.currentTab = item;
}
}
}
</script>
<style scoped>
.active {
color: red;
}
</style>
注意:上面is后的currentTab的值需要是什么内容呢?
- 可以是通过component函数注册的组件
- 在一个组件对象的components对象中注册的组件
动态组件的传值
如果是动态组件我们可以给它们传值和监听事件吗?
- 和基本组件的传值是一样的,只是我们需要将
属性和监听事件
放到component上来使用
二、keep-alive
- 我们对上面的案例中About组件进行改造
- 在其中增加了一个按钮,点击可以递增的功能
- 比如我们将counter点到10,那么在切换到home再切换回来about时,状态是否可以保持呢?
- 答案是否定的
- 这是因为默认情况下,我们在
切换组件后,about组件会被销毁掉,再次回来时会重新创建组件
- 但是,在开发中某些情况我们希望继续保持组件的状态,而不是销毁掉,这个时候我们就可以使用一个内置组件:
keep-alive
keep-alive属性 include
- string | RegExp | Array。只有名称匹配的组件会被缓
存;exclude
- string | RegExp | Array。任何名称匹配的组件都不
会被缓存max
- number | string。最多可以缓存多少组件实例,一旦达
到这个数字,那么缓存组件中最近没有被访问的实例会被销毁- include 和 exclude prop 允许组件有条件地缓存
- 二者都可以用
逗号分隔字符串、正则表达式或一个数组
来表示 - 匹配首先检查组件自身的
name 选项
缓存组件的生命周期
对于缓存的组件来说,再次进入时,我们是不会执行created或者mounted等生命周期函数的 |
---|
- 但是有时候我们确实希望监听到何时重新进入到了组件,何时离开了组件
- 这个时候我们可以使用
activated
和deactivated
这两个生命周期钩子函数来监听
三、异步组件
- Webpack的代码分包
- 默认的打包过程
- 默认情况下,在构建整个组件树的过程中,因为组件和组件之间是通过模块化直接依赖的,那么webpack在打包时就会将组件模块打包到一起(比如一个app.js文件中)
- 这个时候
随着项目的不断庞大
,app.js文件的内容过大
,会造成首屏的渲染速度变慢
- 打包时,代码的分包
- 所以,对于一些不需要立即使用的组件,我们可以单独对它们进行拆分,拆分成一些小的代码块chunk.js
- 这些chunk.js会在需要时从服务器加载下来,并且运行代码,显示对应的内容
- 那么webpack中如何可以对代码进行分包呢?
Vue中实现异步组件 - 如果我们的项目过大了,对于
某些组件
我们希望通过异步的方式来进行加载
(目的是可以对其进行分包处理),那么Vue中给我们提供了一个函数:defineAsyncComponent
- defineAsyncComponent接受两种类型的参数
类型一
:工厂函数,该工厂函数需要返回一个Promise对象类型二
:接受一个对象类型,对异步函数进行配置工厂函数类型的写法
-对象类型一的写法
异步组件和Suspense- Suspense是一个内置的全局组件,该组件有两个插槽
default
:如果default可以显示,那么显示default的内容fallback
:如果default无法显示,那么会显示fallback插槽的内容
<template>
<div>
App组件
<home></home>
<suspense>
<template #default>
<async-category></async-category>
</template>
<template #fallback>
<loading></loading>
</template>
</suspense>
</div>
</template>
<script>
import {
defineAsyncComponent } from 'vue';
import Home from './Home.vue';
import Loading from './Loading.vue';
// import AsyncCategory from './AsyncCategory.vue';
const AsyncCategory = defineAsyncComponent(() => import("./AsyncCategory.vue"))
// const AsyncCategory = defineAsyncComponent({
// loader: () => import("./AsyncCategory.vue"),
// loadingComponent: Loading,
// // errorComponent,
// // 在显示loadingComponent组件之前, 等待多长时间
// delay: 2000,
// /**
// * err: 错误信息,
// * retry: 函数, 调用retry尝试重新加载
// * attempts: 记录尝试的次数
// */
// onError: function(err, retry, attempts) {
// }
// })
export default {
components: {
Home,
AsyncCategory,
Loading
}
}
</script>
<style scoped>
</style>