One of the new features of Vue3 that has been talked about for a while is the idea of Portals – or ways to move template HTML to different parts of the DOM. Portals, which are a common feature in React, were available in Vue2 under the portal-vue library.
Now in Vue3, there is native support for this concept using the Teleport feature.
How Vue Teleport works
Let’s say that we have some child component where we want to trigger a notification to pop up. As we were just discussing, it’s simpler if we render this notification in an entirely separate DOM tree than Vue’s root #app element.
The first thing we would want to do is go to our index.html and add a <div> right before </body>.
index.html
<body>
<div id="app"></div>
<div id='portal-target'></div>
</body>
Next, let’s start creating our component that triggers the notification to render. If you’re not familiar with Vue3, definitely check out this Vue3 introduction!
VuePortals.vue
<template>
<div class='portals'>
<button @click='showNotification'> Trigger Notification! </button>
<teleport to='#portal-target'>
<div class='notification'>
This is rendering outside of this child component!
</div>
</teleport>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup () {
const isOpen = ref(false)
var closePopup
const showNotification = () => {
isOpen.value = true
clearTimeout(closePopup)
closePopup = setTimeout(() => {
isOpen.value = false
}, 2000)
}
return {
isOpen,
showNotification
}
}
}
</script>
<style scoped>
.notification {
font-family: myriad-pro, sans-serif;
position: fixed;
bottom: 20px;
left: 20px;
width: 300px;
padding: 30px;
background-color: #fff;
}
</style>
In this snippet, when the button is pressed, a notification will be rendered for 2 seconds. However, our main goal is to use Teleport to get the notification to render outside our Vue app.
As you can see, Teleport has one required attribute – to
The to attribute takes in a valid DOM query string and it can be the:
- id of an element
- class of an element
- data selector
- a responsive query string
Since we passed it in #portal-target, our Vue app will locate the #portal-target div we included in index.html and it will teleport all the code inside the portal and render it inside that div.