Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to render Vue's main app to the body element?

I am building an admin page in a project that uses a paid-for theme called "pages".

The issue is that in these themes, <nav> and <header> must be direct children of <body>.

When I use Vue to bootstrap the app, I am rendering it to a <div> with an id that's set to root. This then nests the <nav> and <header> within this container (i.e. under <div id="root">).

I have been searching high and low on how to get Vue components to become direct children of body.

How to do this?


What I am getting:

<body>
    <div>
        <nav></nav>
        <header></header>
    </div>
</body>

What the theme needs:

<body>
    <nav></nav>
    <header></header>
</body>
like image 521
James Lewis Avatar asked Mar 13 '17 16:03

James Lewis


2 Answers

With Vue 3 you can do it.

let YourApp = {
  data() {
    return {
      message: 'Hello World!'
    }
  },
  template: `
      <nav>Nav</nav>
      <header>Header</header>
      <span> inspect to see it</span>
  `
}

// Browser Version - vue.global.js
Vue.createApp(YourApp).mount('body')
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.global.min.js"></script>
like image 116
Érick Luís Avatar answered Nov 15 '22 21:11

Érick Luís


With Vue 2.0 you cannot mount root instance to the body or html element. You will be getting [Vue warn]: Do not mount Vue to <html> or <body> - mount to normal elements instead. error message.

The provided element merely serves as a mounting point. Unlike in Vue 1.x, the mounted element will be replaced with Vue-generated DOM in all cases. It is therefore not recommended to mount the root instance to <html> or <body>.

https://vuejs.org/v2/api/#el

The way around is to manually move your element on component mount() event.

<div id="app">
  <navbar :msg="msg"></navbar>

  Lorem ipsum dolor sit amet, consectetur adipisicing elit.

  <button @click="msg = 'tested'">Test 2-way binding</button>
</div>

Example workflow:

new Vue({
    el: '#app',
  data: {
    msg: 'message'
  },
  components: {
    'navbar': {
      template: `<navbar>{{ msg }}</navbar>`,
      props: ['msg'],
      mounted() {
        document.body.insertBefore(this.$el, document.body.firstChild)
      }
    }
  }
})

https://jsfiddle.net/jedrzejchalubek/m9dnsjjr/2/

like image 32
Jędrzej Chałubek Avatar answered Nov 15 '22 23:11

Jędrzej Chałubek