⏳ preface
This is the 26th day of my participation in Gwen Challenge
As you all know, implementing modal boxes and making asynchronous requests is a common occurrence in our normal front-end development. However, both vue2 and native JS implementations are not logically independent enough, so VUe3 has introduced a new approach to solve this problem.
Let’s take a look at how amazing vuE3’s new Teleport is. How to make multiple asynchronous requests in Suspense?
Let’s learn ~📚
👋 use teleport to open the modal box
1. What is teleport
Teleport literally means to send over a long distance. We can understand it as a portal.
As you all know, a portal means to go from one place to another. Why is Vue3 teleport?
In fact, a very common requirement is that we often have to click a button to achieve the effect of the modal box. Before VUe3, we basically controlled it to form a parent-child component relationship after clicking on it, so the feeling of independence was not so strong.
Therefore, Vue3 uses Teleport to solve this problem. Teleport is like a portal, as shown in the picture above. For example, if we click the open button, then after clicking the button, we use the portal to teleport to another location (the modal box Model). Click the close button again, and Modal disappears from the portal Modal box.
Through this explanation, I believe you have a basic understanding of Teleport.
2. Realize the function of modal box
Next we will use this function to implement a modal box that controls the display and hiding of components.
(1) Set the anchor point
We now set an anchor point in the vue3 project /public/index.html to hold the content of the component. The specific code is as follows:
<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>// Define an anchor point first<div id="modal"></div>
<! -- built files will be auto injected -->
</body>
Copy the code
(2) Define subcomponents
Next we define a child component under/SRC/Components, named modal.vue. The specific code is as follows:
<template>
<teleport to="#modal">
<div id="center" v-if="isOpen">
<h2><slot>this is a modal</slot></h2>
<button class="btn2" @click="buttonClick">Close</button>
</div>
</teleport>
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
// The parent component needs to pass the data to the child component via props, which can be an array or an object
props: {
isOpen: Boolean,},// The child passes data to the parent
// Use emits to more explicitly display the component's custom events
emits: {
'close-modal': null
},
//props corresponds to the content of props
// The context name can be customized as long as it corresponds to the top and bottom to trigger the emit content
setup(props, context){
const buttonClick = () = > {
context.emit('close-modal')}return{
buttonClick
}
}
})
</script>
<style>
#center{
width:200px;
height:200px;
border:2px solid rgb(105.165.56);
text-align: center;
border-radius: 2px;
margin: 50px auto 0;
}
.btn2{
background: #1971c9;
border:none;
padding: 8px;
border-radius: 5px;
color: #fff;
cursor: pointer;
}
</style>
Copy the code
(3) Define the parent component
Then we’ll define a parent component called index.vue. The specific code is as follows:
<template>
<button class="btn1" @click="openModal">Open the modal box</button>
<modal :isOpen="modalIsOpen" @close-modal="onModalClose">
My Modal!!!
</modal>
</template>
<script lang="ts">
import { ref, defineComponent} from 'vue'
import Modal from './components/Modal.vue'
export default defineComponent({
name: 'App'.components: {
Modal
},
setup(){
// Add responsive objects to control whether to display
const modalIsOpen = ref(false)
// Open the modal box event
const openModal = () = > {
modalIsOpen.value = true
}
// Close the modal box event
const onModalClose = () = > {
modalIsOpen.value = false
}
return{
modalIsOpen,
openModal,
onModalClose
}
}
});
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2d4c6b;
margin-top: 60px;
}
.btn1{
background: #1971c9;
border:none;
padding: 16px;
border-radius: 5px;
color: #fff;
cursor: pointer;
}
</style>
Copy the code
Now let’s take a look at the browser display:
As you can see, by teleport, the modal boxes are now successfully displayed at the same level as the div with the ID app, which is independent of each other, rather than the parent and child level.
In the example above, we learned how to render a component to another DOM node using vue3’s new Teleport feature, which makes components more independent.
🤚 Use Suspense to initiate an asynchronous request
Suspense 1. What is Suspense
We all know that in the Web world, there are a lot of asynchronous request dilemmas. When making asynchronous requests, we often need to determine the status of these asynchronous requests, and then display different interfaces based on these requests.
Suspense is a special component with two template slots that renders feedback content at first. It doesn’t render formal content until a certain condition is reached. Which is the content of default. As a result, rendering asynchronous content is much easier.
It’s also worth noting that if you use Suspense, you return a promise instead of an object.
Make an asynchronous request with Suspense
Next we use Suspense to make an asynchronous request.
First of all, we define a sub-component under the project named Asyncshow. vue. The specific code is as follows:
<template>
<h1>{{result}}</h1>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
setup() {
To use Suspense you need to return an object
return new Promise((resolve) = > {
setTimeout(() = > {
return resolve({
result: '10000'})},3000)})}})</script>
Copy the code
Then define a parent component under the project named dogshow.vue as follows:
<template>
<div id="app">
<Suspense>
<template #default>
<async-show />
</template>
<template #fallback>
<h1>Loading ! .</h1>
</template>
</Suspense>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import AsyncShow from './components/AsyncShow.vue'
export default defineComponent({
name: 'App'.components: {
AsyncShow,
},
setup(){}});</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
h1 {
font-size: 6rem;
}
</style>
Copy the code
The final browser display looks like this:
As you can see, it is easy to initiate an asynchronous request through Suspense. The state is fallback at the beginning, and then it switches to default after 3s, and the corresponding asynchronous request content is displayed.
Make multiple asynchronous requests with Suspense
We’re not content with the status quo, and the Internet is so weird that we can’t just keep sending one asynchronous request! So, let’s implement the effect of making multiple asynchronous requests.
So first we’re going to make a request using a free online API. Next, in the components file of the project, we define a child component named dogshow. vue. The code is as follows:
<template>
<img :src="result && result.message">
</template>
<script lang="ts">
import axios from 'axios'
import { defineComponent } from 'vue'
export default defineComponent({
async setup() {
const rawData = await axios.get('https://dog.ceo/api/breeds/image/random')
return {
result: rawData.data
}
}
})
</script>
Copy the code
Next we add the content of the above child component to the parent component as follows:
<template>
<div id="app">
<Suspense>
<template #default>
<async-show />
<dog-show />
<template #fallback>
<h1>Loading ! .</h1>
</template>
</Suspense>
</div>
</template>
<script lang="ts">
import AsyncShow from './components/AsyncShow.vue'
import DogShow from './components/DogShow.vue'
export default {
name: 'App'.components: {
AsyncShow,
DogShow
},
setup(){}};</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
h1 {
font-size: 6rem;
}
</style>
Copy the code
The final browser display looks like this:
As you can see, we are making two asynchronous requests at the same time and using them in Suspense’s Default slot. Again, the browser will display the content of the Fallback first, and when the time is right, it will display the requested content.
In this case, showing more requests is just as effective. In contrast, sending multiple asynchronous requests is much more convenient.
4. How to catch errors
After learning the above, I believe you have some idea of how to use Suspense. Well, the network request is strange, can’t always be a smooth initiation of the request, right? So, we need to learn again, when the network request fails, how to catch Supsense wrapped error.
There is a hook function called onErrorCaptured that you can use to capture something.
We will modify the parent component index.vue with the following code:
<template>
<div id="app">
<p>{{error}}</p>
<Suspense>
<template #default>
<async-show />
<dog-show />
<template #fallback>
<h1>Loading ! .</h1>
</template>
</Suspense>
</div>
</template>
<script lang="ts">
import { onErrorCaptured } from 'vue'
import AsyncShow from './components/AsyncShow.vue'
import DogShow from './components/DogShow.vue'
export default {
name: 'App'.components: {
AsyncShow,
DogShow
},
setup() {
const error = ref(null)
onErrorCaptured((e: any) = > {
error.value = e
return true
})
return{
error
}
}
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
h1 {
font-size: 6rem;
}
</style>
Copy the code
At this point, we will modify dogshow. vue’s interface to make it an invalid API. The code is as follows:
const rawData = await axios.get('https://dog.ceo/api/breeds/image')
Copy the code
Let’s take a look at how the browser works:
As you can see, after making the API invalid, the dog images are no longer displayed, and onErrorCaptured life cycle is captured at the top.
3. Conclusion 🖐️
That’s the end of Teleport and Suspense! You’ll also get a sense of the wonders of portals and how Suspense is unique.
Vue3 keep learning and updating…
- Pay attention to the public number Monday laboratory, the first time to pay attention to learning dry goods, more interesting columns for you to unlock ~
- If this article is useful to you, remember to click three times before going oh ~
- See you next time! 🥂 🥂 🥂