How to generate vue component in body?

45 Views Asked by At

I want to create a popup component that will be placed at the end of the body.

I saw this in vuetify, but due to the complexity of the structure, I couldn't find in the source code which function put this element there.

It is necessary that the component be placed at the bottom of the body when created, and removed when unmounted. At the same time, so that you can receive emits from it and pass parameters

example with vuetify

2

There are 2 best solutions below

0
FMa On

Check out v-snackbar in vuetify. That might be what you are looking for.

0
tao On

This should do it:

const div = document.createElement('div');
document.body.appendChild(div);
Vue.createApp(componentDefinition).mount(div)

Please note you've asked a XY question. Most likely, if you asked about how to fix the problem you're trying to fix by placing a component at the end of <body /> I would have given you a more useful answer, solving the actual problem.


Here's how a <Teleport /> implementation would look like:

const { createApp, ref } = Vue
const app = createApp({
  setup: () => ({
    open: ref(false),
    foo: ref('bar')
  })
})
app.mount('#app')
.modal {
  position: fixed;
  z-index: 999;
  inset: 0;
  display: flex;
  justify-content: center;
  align-items: center;
}
.modal-backdrop {
  position: absolute;
  inset: 0;
  background-color: rgba(0,0,0,.42);
}
.modal-content {
  position: relative;
  z-index: 1;
  padding: 1rem;
  max-width: 300px;
  background-color: white;
  border-radius: 0.5rem;
  box-shadow: 0 5px 6px -3px rgba(0,0,0,.1),0 9px 12px 1px rgba(0,0,0,.07),0 3px 16px 2px rgba(0,0,0,.06)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.8/vue.global.prod.min.js"></script>
<div id="app">
  <input v-model="foo" /><br />
  <pre>{{ { foo } }}</pre>
  <button @click="open = true">Open Modal</button>
  
  <Teleport to="body">
    <div v-if="open" class="modal">
      <div class="modal-backdrop" @click="open = false"></div>
      <div class="modal-content">
        <p>Hello from the modal!</p>
        <input v-model="foo" />
        <pre>{{ { foo } }}</pre>
        <button @click="open = false">Close</button>
      </div>
    </div>
  </Teleport>
</div>

As can be observed, although the modal is teleported to body, it still has access to the test model of foo. In fact, from Vue's perspective, the modal is still a child node of App, so if there were any props involved, everything would work disregarding the fact that the actual DOM element is rendered elsewhere.