One of Vue.js’ greatest strengths is it’s ability to be used to enhance or replace parts of older apps or even static pages. This progressive nature allows Vue to be incrementally adopted or just used to improve a pre-existing app. portal-vue by Linus Borg extends this flexibility by allowing Vue components to be rendered to anywhere in the DOM, outside of their parent components, or even the whole Vue app!
Install portal-vue via. Yarn or NPM.
# Yarn
$ yarn add portal-vue
# NPM
$ npm install portal-vue --save
Now, enable the PortalVue plugin.
import Vue from 'vue';
import PortalVue from 'portal-vue';
import App from 'App.vue';
Vue.use(PortalVue);
new Vue({
el: '#app',
render: h => h(App)
});
So, let’s create the source component that creates the original portal. It can have it’s own content as well, only stuff inside the portal component gets moved.
<template>
<div>
<portal to="other-component">
<p>{{message}}</p>
</portal>
<p>Other stuff stays here.</p>
</div>
</template>
<script>
export default {
data() {
return {
message: 'I get rendered in OtherComponent!'
}
}
}
</script>
Now, as long as both AComponent and OtherComponent are rendered, the content from AComponent’s portal will end up rendered in OtherComponent. You can even have multiple portals in a single component, going different places!
<template>
<div>
<portal-target name="other-component">
</portal-target>
<p>I have my own stuff too!</p>
</div>
</template>
With a teeny-tiny change, we can have the portal content output to anywhere in the DOM of the entire webpage!
<template>
<div>
<portal target-el="#place-on-the-page">
<p>{{message}}</p>
</portal>
<p>Other stuff stays here.</p>
</div>
</template>
<script>
export default {
data() {
return {
message: 'I get rendered in the element with the id #place-on-the-page!'
}
}
}
</script>
Now, as long as both AComponent and OtherComponent are rendered, the content from AComponent’s portal will end up rendered in OtherComponent. You can even have multiple portals in a single component, going different places!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Vue-Portal Example</title>
</head>
<body>
<!-- Vue app -->
<div id="app">
...
</div>
<script src="/dist/build.js"></script>
<!-- Other random stuff on the page -->
<section class="something-else">
<h4>What is going on here! Who let the Vue app out?</h4>
<!-- Contents of the portal replace the div here -->
<div id="place-on-the-page">
</div>
</section>
</body>
</html>
Neat, huh?
See an in-depth explanation here.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Is the opposite feasible? Have a slot somewhere in my application where I would like an element outside the app to move in?