异步组件
在大型应用中,我们可能需要将应用分割成小一些的代码块 并且减少主包的体积(不需要在首屏加载得都可使用异步组件)
这时候就可以使用异步组件
顶层 await
在setup语法糖里面 使用方法
<script setup>
中可以使用顶层 await
。结果代码会被编译成 async setup()
<script setup>
const post = await fetch(`/api/post/1`).then(r => r.json())
</script>
父组件引用子组件 通过defineAsyncComponent加载异步配合import 函数模式便可以分包
<script setup lang="ts">
import { reactive, ref, markRaw, toRaw, defineAsyncComponent } from 'vue'const Dialog = defineAsyncComponent(() => import('../../components/Dialog/index.vue'))//完整写法const AsyncComp = defineAsyncComponent({// 加载函数loader: () => import('./Foo.vue'),// 加载异步组件时使用的组件loadingComponent: LoadingComponent,// 展示加载组件前的延迟时间,默认为 200msdelay: 200,// 加载失败后展示的组件errorComponent: ErrorComponent,// 如果提供了一个 timeout 时间限制,并超时了// 也会显示这里配置的报错组件,默认值是:Infinitytimeout: 3000
})
内置组件suspense
<suspense>
组件有两个插槽。它们都只接收一个直接子节点。default
插槽里的节点会尽可能展示出来。如果不能,则展示 fallback
插槽里的节点。
<Suspense><template #default><Dialog><template #default><div>我在哪儿</div></template></Dialog></template><template #fallback><div>loading...</div></template></Suspense>
代码案例
父组件
<template><div class=""></div><suspense><template #default><Eleven></Eleven></template><template #fallback><div>loading.....也可使用骨架屏代替</div></template></suspense>
</template><script setup lang="ts">
import { ref, reactive, defineAsyncComponent } from "vue";
// import Eleven from "./components/eleven.vue";
const Eleven = defineAsyncComponent(() => import("./components/eleven.vue")
);
</script><style lang="less" scoped></style>
eleven.vue
<template><div class="" v-for="(iten, index) in data" :key="index">{{ iten?.name }}</div>
</template><script setup lang="ts">
import { ref, reactive } from "vue";
import { axiosXhr } from "./eleven_server";
let data = await axiosXhr("./data.json");
console.log(data);
</script><style lang="less" scoped></style>
eleven_server.ts
export const axiosXhr = (url: string) => {return new Promise((resolve) => {let xhr = new XMLHttpRequest();xhr.open("GET", url);xhr.onreadystatechange = () => {console.log(xhr);if (xhr.readyState === 4 && xhr.status === 200) {setTimeout(() => {resolve(JSON.parse(xhr.responseText));}, 2000);}};xhr.send();});
};
data.json
[{"name": "cookie1"},{"name": "cookie2"}
]
效果图:
先加载fallback节点文本,2s后再加载匿名插槽节点
内置组件teleport
Teleport Vue 3.0新特性之一。
Teleport 是一种能够将我们的模板渲染至指定DOM节点,不受父级style、v-show等属性影响,但data、prop数据依旧能够共用的技术;类似于 React 的 Portal。
主要解决的问题 因为Teleport节点挂载在其他指定的DOM节点下,完全不受父级style样式影响
使用方法
通过to 属性 插入指定元素位置 to="body" 便可以将Teleport 内容传送到指定位置
<Teleport to="body"><Loading></Loading>
</Teleport>
动态控制teleport
使用disabled 设置为 true则 to属性不生效 false 则生效
<teleport :disabled="true" to='body'><A></A></teleport>
代码案例
父组件:
<template><div class="parent"><!--disabled 默认false --><teleport :disabled="false" to="body"><Twelve></Twelve></teleport></div>
</template><script setup lang="ts">
import { ref, reactive } from "vue";
import Twelve from "./components/twelve.vue";
</script><style lang="less" scoped>
.parent {width: 100vw;height: 50vh;background-color: pink;position: relative; // 这样会改变弹窗的位置
}
</style>
子组件twelve.vue
<template><div class="dialog">弹窗</div>
</template><script setup lang="ts">
import { ref, reactive } from "vue";
</script><style lang="less" scoped>
.dialog {width: 200px;height: 200px;background-color: black;position: absolute;left: 50%;top: 50%;
}
</style>
效果图: