「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」
⏳ 前言
本文是根据某课网Vue3系统精讲学习过程所做的笔记,如有偏差错误欢迎大佬指正ya!
🚪 Teleport--瞬移组件的位置
可以将子组件中使用的全局组件通过teleport渲染到全局dom节点下,避免造成组件嵌套过深,对组件造成干扰。例如,将全局提示框toast
挂载到与#app
同级的全局DOM节点下:
- 定义锚点
- 在Toast组件中使用teleport
- 调用Toast组件
<!-- index.html -->
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- 定义锚点 -->
<div id="toast"></div>
</body>
// Toast.vue
<template>
<teleport to="#toast"> // 将toast传送到id为toast的dom节点下
<div class="container">
Toast
</div>
</teleport>
</template>
<script>
export default {
name: "",
setup() {
return {
}
}
}
</script>
<style scoped>
</style>
🚚 Suspense--异步加载的新福音
Suspense,它有两个template-slot,刚开始会渲染#fallback
的内容,直到达到某个条件后会渲染#default
的内容。特别注意,如果使用Suspense的话,需要在setup中返回一个promise来管理组件的状态(resolve/reject)。
单个异步组件
首先先创建一个子组件,并命名为AsyncShow
// AsyncShow.vue
<template>
<div class="container">
<h1>{{result}}</h1>
</div>
</template>
<script>
import { defineComponent } from "vue"
export default defineComponent({
name: "",
setup() {
return new Promise((resolve) => {
setTimeout(() => {
return resolve({
result: 3000
})
}, 3000)
})
}
})
</script>
<style>
</style>
然后在App组件中调用AsyncShow
<template>
<div id="app">
<Suspense>
<template #default>
<AsyncShow />
</template>
<template #fallback>
Loading...
</template>
</Suspense>
</div>
</template>
<script>
import AsyncShow from './components/AsyncShow.vue';
export default {
name: "App",
setup() {
// ...
},
components: { AsyncShow }
}
</script>
<style>
</style>
运行项目可以看到页面中一开始展示组件fallback
时的状态Loading,三秒后当组件resolved后,切换至default
状态的结果3000
多个异步组件
同样的,我们可以同时调用多个异步组件,
新建一个CatShow
组件用于异步请求catapi获取猫片
<template>
<div class="container">
<img :src="result && result.url" alt="">
</div>
</template>
<script>
import { defineComponent } from "vue"
import axios from 'axios'
export default defineComponent({
name: "",
async setup() {
const rawData = await axios.get('https://api.thecatapi.com/v1/images/search')
console.log(rawData);
return {
result: rawData.data[0]
}
}
})
</script>
然后在App组件中调用:
<template>
<div id="app">
<Suspense>
<template #default>
<div>
<AsyncShow />
<CatShow />
</div>
</template>
<template #fallback>
Loading...
</template>
</Suspense>
</div>
</template>
<script>
import AsyncShow from './components/AsyncShow.vue';
import CatShow from './components/CatShow.vue';
export default {
name: "App",
setup() {
// ...
},
components: { AsyncShow, CatShow }
}
</script>
运行后可以看到一开始页面显示Loading,3s后页面显示AsyncShow
的结果3000和CatShow
返回的一张猫片
抓取错误
在使用Suspense请求多个异步组件后,我们需要学习如何抓取异步请求的错误,毕竟网络请求可能会各种各样的原因引起错误,我们应该如何抓取Suspense包裹下的组件发生的错误呢?
我们可以使用Vue3自带的钩子函数onErrorCaptured
,这个钩子函数需要返回一个布尔值,表示是否向上传播
<template>
<div id="app">
<Suspense>
<template #default>
<div>
<AsyncShow />
<CatShow />
</div>
</template>
<template #fallback>
Loading...
</template>
</Suspense>
{{error}}
</div>
</template>
<script>
import { computed, reactive, ref, toRefs } from '@vue/reactivity';
import { onErrorCaptured } from '@vue/runtime-core';
import AsyncShow from './components/AsyncShow.vue';
import CatShow from './components/CatShow.vue';
export default {
name: "App",
setup() {
const error = ref(null)
onErrorCaptured((e) => {
error.value = e
return true
})
return {
error
};
},
components: { AsyncShow, CatShow }
}
</script>
然后我们在CatShow
中将请求url修改
const rawData = await axios.get('https://dog.ceo/api/breeds/image')
我们可以在页面中看到钩子函数捕获到的错误了