Vue3动态、异步组件-keepalive的使用方法
动态组件:让多个组件使用同一个挂载点,并动态切换,这就是动态组件。
动态组件的使用
使用 v-if 判断切换组件
1<template>
2<div id="app">
3 <button v-for="item in list" :class="{active:currentType===item}" :key="item" @click="ChangeTab(item)">{{item}}</button>
4<!--方案一 使用v-if判断切换组件-->
5 <template v-if="currentType=="home"">
6 <home></home>
7 </template>
8 <template v-else-if="currentType=="category"">
9 <category></category>
10 </template>
11 <template v-else>
12 <about></about>
13 </template>
14
15</div>
16</template>
17
18<script>
19import Home from "./views/Home"
20import Category from "./views/Category";
21import About from "./views/About";
22export default {
23 name: "App",
24 components:{Home,Category,About},
25 data(){
26 return{
27 list:["home","about","category"],
28 currentType:"home"
29 }
30 },
31 methods:{
32 ChangeTab(item){
33 this.currentType = item
34 }
35 }
36}
37</script>
使用动态组件切换组件
动态组价是使用
component
组件,通过一个特殊的attribute is
来实现
代码示例
1<template>
2<div id="app">
3 <button v-for="item in list" :class="{active:currentType===item}" :key="item" @click="ChangeTab(item)">{{item}}</button>
4<!-- 方案二 使用动态组件切换组件-->
5 <component :is="currentType"></component>
6</div>
7</template>
8
9<script>
10import Home from "./views/Home"
11import Category from "./views/Category";
12import About from "./views/About";
13export default {
14 name: "App",
15 components:{Home,Category,About},
16 data(){
17 return{
18 list:["home","about","category"],
19 currentType:"home"
20 }
21 },
22 methods:{
23 ChangeTab(item){
24 this.currentType = item
25 }
26 }
27}
28</script>
attribute is
的值就是全局注册
、局部注册
的组件
全局注册
1Vue.component("my-component-name", { /* ... */ })
局部注册
1var ComponentA = { /* ... */ }
2var ComponentB = { /* ... */ }
3new Vue({
4 el: "#app",
5 components: {
6 "component-a": ComponentA,
7 "component-b": ComponentB
8 }
9})
动态组件的传值
在
Home.vue
组件中自定义pageClick
事件传递给父组件
1<template>
2<div class="home"><h2>home组件</h2>{{name}}-{{age}} <button @click="homeClick">点击发送事件</button> </div>
3</template>
4
5<script>
6export default {
7 name: "Home",
8 props:{
9 name:{
10 type:String,
11 default: ""
12 },
13 age:{
14 type:Number,
15 default: 18
16 }
17 },
18 emits:["pageClick"],
19 methods:{
20 homeClick(){
21 this.$emit("pageClick")
22 }
23 }
24}
25</script>
父组件接收子组件传递过来的
pageClick
事件
1<template>
2<div id="app">
3 <button v-for="item in list" :class="{active:currentType===item}" :key="item" @click="ChangeTab(item)">{{item}}</button>
4 <component :is="currentType" name="acmen" :age="20" @pageClick="pageClick"></component>
5</div>
6</template>
7
8<script>
9import Home from "./views/Home"
10import Category from "./views/Category";
11import About from "./views/About";
12export default {
13 name: "App",
14 components:{Home,Category,About},
15 data(){
16 return{
17 list:["home","about","category"],
18 currentType:"home"
19 }
20 },
21 methods:{
22 ChangeTab(item){
23 this.currentType = item
24 },
25 // 使用子组件传递过来的事件
26 pageClick(){
27 console.log("pageClick")// pageClick
28 }
29 }
30}
31</script>
使用 keep-alive
假设,我们还使用以上的三个组件进行切换,我的About.vue
组件中加了一个按钮,点击每次加一
,当我再次切换到Home.vue
组件后,我又切换到About.vue
组件,这时候我发现上次点击到10
了,现在又变成0
,解决这个问题我们要使用keep-alive
使用
keep-alive
对我们的组件进行一层包裹就可以了
1 <keep-alive>
2 <component :is="currentType" name="acmen" :age="20" @pageClick="pageClick"></component>
3 </keep-alive>
keep-alive 的三种属性
include
使用方法 注意:在使用include
的时候,首先要检查自身的name选项
1<script>
2export default {
3 name: "Home"
4</script>
5
使用方法 使用,
1 <keep-alive include="home,about">
2 <component :is="currentType" name="acmen" :age="20" @pageClick="pageClick"></component>
3 </keep-alive>
Webpack 分包
我们在做开发的时候会写很多封装的函数方法,在组件中使用,比如我在项目中新建一个
utils
文件夹中存入一个math.js
里面存放一个简单的例子
1export function sum(n,m){
2 return n+m
3}
我们在main.js
中使用这个方法
1import { createApp } from "vue"
2import App from "./12_异步组件的使用/App"
3import {sum} from "../utils/math"
4console.log(sum(10,20))
5createApp(App).mount("#app")
在打包的时候,它会打包到app.js
,中。
我现在希望在打包的时候它会单独的给我打包到一个js
中
代码如下
1import { createApp } from "vue"
2import App from "./12_异步组件的使用/App"
3// import {sum} from "../utils/math"
4// console.log(sum(10,20))
5
6//使用import函数导入的模块,后续webpack对其进行打包的时候就会进行分包的操作
7import("../utils/math").then((res)=>{
8 res.sum(10,20)
9})
10createApp(App).mount("#app")
异步组件的使用
写法一 返回 Promise
1<template>
2<div id="app">
3 <h1>App组件</h1>
4 <home></home>
5 <async-about></async-about>
6</div>
7</template>
8
9<script>
10import {defineAsyncComponent} from "vue";
11import Home from "./Home"
12//写法一 返回Promise
13const AsyncAbout = defineAsyncComponent(()=>import("./asyncAbout.vue"))
14export default {
15 name: "App",
16 components:{Home,AsyncAbout}
17}
18</script>
写法二 使用对象写法
1const AsyncAbout = defineAsyncComponent({
2 loader:()=>import("./asyncAbout"),
3 // 组件在加载的时候,显示一个占位的组件
4 loadingComponent:组件名,
5 //组件在加载的时候,失败显示的组件
6 // errorComponent:组件名,
7 //在我们现在loadingComponent组件之前等待多长时间
8 delay:2000,
9 /**
10 *
11 * @param err 错误信息
12 * @param retry 函数,调用retry尝试重新加载
13 * @param attempts 记录尝试的次数
14 */
15 onError:function (err,retry,attempts){
16
17 }
18})
异步组件和 Suspense 结合使用
1 <suspense>
2<!-- 能显示就显示默认的-->
3 <template #default><async-about></async-about></template>
4<!-- 不能显示 就显示应急组件-->
5 <template #fallback><loading></loading></template>
6 </suspense>