Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue component not mounting or rendering and no error messages

I have the following 2 components

BrewTitle.vue

<template>
    <h1>{{ title }}</h1>
</template>

<script>
export default {
  data() {
    return {
      title: "Brew Title"
    };
  },
  created() {
    console.log("title created")
  }
};
</script>

Snackbar.vue

<template>
    <h1>{{ title }}</h1>
</template>

<script>
export default {
  data() {
    return {
      title: "Brew Title"
    };
  },
    created() {
        console.log("snackbar created")
    }
};
</script>

How they are added to the index.js file

import Vue from "vue";

import BrewTitle from "./components/BrewTitle";
import Snackbar from "./components/Snackbar";

Vue.component("brewtitle", BrewTitle);
Vue.component("snackbar", Snackbar);

const app = new Vue({
  el: "#app"
});

In my html template I have the following snippet

<div id="app">
<brewtitle />
<snackbar />
</div>
<script src="main.js"></script>

The components are almost identical, but the snackbar is nowhere to be found on the html page or in the view browser extension. There are no problems with webpack and there is no message in the browser.

What am I doing wrong?

like image 316
kristian nissen Avatar asked Jul 08 '19 19:07

kristian nissen


1 Answers

Browsers don't support self-closing tags like these:

<brewtitle />
<snackbar />

Try having explicit closing tags instead:

<brewtitle></brewtitle>
<snackbar></snackbar>

If you use a self-closing tag for a component then the browser will just treat it as an opening tag. An implicit closing tag will be created when the parent element closes. That'll work fine if there are no other siblings but it will go wrong when there are.

So taking your original code as an example:

<div id="app">
  <brewtitle />
  <snackbar />
</div>

The <brewtitle> won't count as closed until it reaches the closing </div>. So this is equivalent to:

<div id="app">
  <brewtitle>
    <snackbar></snackbar>
  </brewtitle>
</div>

So <snackbar> will be treated as a child of <brewtitle>. As brewtitle doesn't have a slot the snackbar will just be discarded.

This only applies if the HTML is being parsed directly by the browser. For anything parsed by Vue itself, such as in your .vue files, this won't be a problem.

From the official Vue documentation, https://v2.vuejs.org/v2/style-guide/#Self-closing-components-strongly-recommended

Components with no content should be self-closing in single-file components, string templates, and JSX - but never in DOM templates.

...

Unfortunately, HTML doesn’t allow custom elements to be self-closing - only official “void” elements.

like image 170
skirtle Avatar answered Oct 03 '22 03:10

skirtle