# Suspense
Suspense
组件是vue3
新增的内置组件,主要作为在等待异步组件时渲染一些后备内容,创建一个平滑的用户体验。
说到这里是不是很熟悉,这不就是类似于骨架图或者占位图。
// parent.vue
<template>
<div id="app">
<Suspense>
<template #default>
<hello-world />
</template>
<template #fallback>
<div>
loading......
</div>
</template>
</Suspense>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue';
export default {
components: {
HelloWorld,
},
setup() {
}
};
</script>
这里需要注意Suspense
组件内部的template
需要有一个根节点,而不是多个
// HelloWorld
<template>
<div>
<div>{{msg}}</div>
</div>
</template>
<script>
export default {
async setup() {
const fetchMsg = (timeout) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('Hello Suspense')
}, timeout);
});
};
const msg = await fetchMsg(2000)
return { msg }
},
};
</script>
简单的suspense
就成功了,在2000ms之前都是现实的loading......
,之后显示Hello Suspense
# 捕获组件错误
// parent.vue
<template>
<div id="app">
<div v-if="error">{{ error }}</div>
<Suspense v-else>
<template #default>
<hello-world />
</template>
<template #fallback>
<div>
loading......
</div>
</template>
</Suspense>
</div>
</template>
<script>
import { onErrorCaptured, ref } from "vue";
import HelloWorld from './components/HelloWorld.vue';
export default {
components: {
HelloWorld,
},
setup() {
const error = ref(null);
onErrorCaptured((e) => {
error.value = e;
// 不对错误进行拦截
return true;
});
return {error}
}
};
</script>
onErrorCaptured
钩子函数都会在捕获到任何后代组件的错误时运行。如果出现问题,我们可以将其与Suspense
一起使用以渲染错误。
# Teleport
to
-string
。需要prop
,必须是有效的查询选择器或HTMLElement
(如果在浏览器环境中使用)。指定将在其中移动<teleport>
内容的目标元素
<!-- 正确 -->
<teleport to="#some-id" />
<teleport to=".some-class" />
<teleport to="[data-teleport]" />
<!-- 错误 -->
<teleport to="h1" />
<teleport to="some-string" />
disabled
-boolean
。此可选属性可用于禁用<teleport>
的功能,这意味着其插槽内容将不会移动到任何位置,而是在您在周围父组件中指定了<teleport>
的位置渲染
<teleport to="#popup" :disabled="displayVideoInline">
<video src="./my-movie.mp4">
</teleport>
Teleport
提供了一种干净的方法,允许我们控制在 DOM
中哪个父节点下呈现 HTML
,而不必求助于全局状态或将其拆分为两个组件。
<template>
<h1>teleport</h1>
<div class="top" @click="getTop">top</div>
<div class="bot" @click="getBot">bot</div>
<teleport :to="pos">
<div>I'm a teleported!</div>
</teleport>
</template>
<script>
import { ref } from "vue";
export default {
setup() {
// 这里pos需要一个不为空的默认值, 不然会导致元素两次加载
const pos = ref(".top");
const getTop = () => {
console.log("click top");
pos.value = ".top";
};
const getBot = () => {
console.log("click bot");
pos.value = ".bot";
};
return {
pos,
getTop,
getBot,
};
},
};
</script>
请注意,这将移动实际的 DOM
节点,而不是被销毁和重新创建,并且它还将保持任何组件实例的活动状态。所有有状态的 HTML
元素 (即播放的视频) 都将保持其状态。