3
votes

I'm new to Vue and am having some trouble with a few things. First, off I was following this tutorial: eventbus. If I put all the code (html, JS and CSS) in one html file, this works just as described in this tutorial.

However, I have been reading and I was following a VUE cli app structure. I used vue init webpack vueapp01 So, I have an index.html file in the vueapp01 root folder, in the src folder I have an app.vue and two vue files in the components folder; the-box.vue and the-button.vue; along with all the other files loaded by the vue template webpack.

Instead of having all the code in one html file (which works) I have the code separated out like this: index.html:

<!DOCTYPE html>
<html>
 
<head>
    <meta charset="utf-8">
    <title>vueapp01</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script> 
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>
App.vue:

<template>
<div id="the-example" class="container">
  <h1>Building an Event Bus with <a href="https://vuejs.org" target="_blank">Vue.js</a></h1>
  <div class="row">  
    <div class="col-xs-6">
      <the-button what="Event #1"></the-button>
      <the-button what="Event #2"></the-button>
      <the-button what="Event #3"></the-button>
    </div>
    <div class="col-xs-6">
      <the-box name="Receiver #1"></the-box>  
    </div>
  </div>
</div>
  </div>   
</template>

<script>
    import the-button from './components/the-button'
    import the-box from './components/the-box'

    export default {
      name: 'app',
      components: {
        the-button,the-box
      }
    }
</script>
<--
<script>
/******************************************
The Central Event Bus Instance
*******************************************/
let EventBus = new Vue();

</script>
the-box.vue:

/******************************************
Example Root Vue Instance
*******************************************/
new Vue({el: "#the-example"});

/******************************************
A sample Vue.js component that emits an event
*******************************************/

let TheButton = Vue.extend({
	name: "the-button",
  props: ["what"],
  template: `
  	<button class="btn btn-md btn-success the-button" @click="makeItHappen()">Sender: {{what}}</button>
  `,
  methods: {
  	makeItHappen: function(){
    	EventBus.$emit("somethingHappened", this.what)
    }
  }
});

Vue.component("the-button", TheButton);
the-button.vue:

/******************************************
A sample Vue.js component that received an event
*******************************************/

let TheBox = Vue.extend({
	name: "the-box",
  props: ["name"],
  template: `
  	<div class="well">
    	<div class="text-muted">{{name}}</div>	
    	<div>{{respondedText}}</div>
     </div>
  `,
  data: function(){
  	return {
    	respondedText: null
    }
  },
	created: function(){
  	EventBus.$on('somethingHappened', (what)=>{
    	this.respondedText = 'Event Received: ' + what;
    })
  	console.log("Responder")
  }

});

Vue.component("the-box", TheBox);

Currently, I'm getting the errors, "unknown custom element the-box", "unknown custom element the-button". I've tried switching the script and template orders to have templates load first but I still have no luck.

Any help would be greatly appreciated. Also, I assume I'm doing this correctly by separating these components out to separate files but if that is incorrect I'd gladly take criticism on the way I'm learning to use Vue.

2
import the-button from './components/the-button' is not valid javascript. I'm not sure how you are getting as far as you say you are. You can't have a dash in a variable.Bert
@Bert I just changed them throughout the code to not include the dash and I still have the same errors popping up.Paul Toone
When you import a single file component, you typically have to specify the extension so that it will be run through vue-loader. So are you using import TheButton from './components/the-button.vue'? Note the extension.Bert
@Bert, I made that change too and it still gave errors unknown custom element. Also, I'm including the jsfiddle example I'm working from: jsfiddle.net/arvidkahl/gxdn6ycv/… I just want to learn how to take a bus example that works when I put it all in the app.vue file and separate it out into an app.vue file while also importing componentsPaul Toone

2 Answers

3
votes

Change:

import the-button from './components/the-button'
import the-box from './components/the-box'

to

import TheButton from './components/the-button'
import TheBox from './components/the-box'

and do

components: {
  TheButton,
  TheBox,
}

There must be another far larger error somewhere you're somehow not seeing.

2
votes

Here is a full example of how the files should look to implement that fiddle in single file components assuming you used vue init webpack <project>.

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>bus</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

main.js

import Vue from 'vue'
import App from './App'

Vue.config.productionTip = false

window.EventBus = new Vue()

new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
})

App.vue

<template>
<div id="the-example" class="container">
  <h1>Building an Event Bus with <a href="https://vuejs.org" target="_blank">Vue.js</a></h1>
  <div class="row">  
    <div class="col-xs-6">
      <the-button what="Event #1"></the-button>
      <the-button what="Event #2"></the-button>
      <the-button what="Event #3"></the-button>
    </div>
    <div class="col-xs-6">
      <the-box name="Receiver #1"></the-box>  
      <the-box name="Receiver #2"></the-box>  
      <the-box name="Receiver #3"></the-box>  

    </div>
  </div>
</div>
</template>

<script>
    import TheButton from './components/TheButton.vue'
    import TheBox from './components/TheBox.vue'

    export default {
      name: 'app',
      components: {
        TheButton, TheBox
      }
    }
</script>

components/TheBox.vue

<template>
    <div class="well">
        <div class="text-muted">{{name}}</div>  
        <div>{{respondedText}}</div>
    </div>
</template>

<script>
export default {
    name: "the-box",
  props: ["name"],
  data: function(){
    return {
        respondedText: null
    }
  },
    created: function(){
    EventBus.$on('somethingHappened', (what)=>{
        this.respondedText = 'Event Received: ' + what;
    })
    console.log("Responder")
  }

}
</script>

components/TheButton.vue

<template>
    <button class="btn btn-md btn-success the-button" @click="makeItHappen()">Sender: {{what}}</button>
</template>

<script>
export default {
    name: "the-button",
  props: ["what"],
  methods: {
    makeItHappen: function(){
        EventBus.$emit("somethingHappened", this.what)
    }
  }

}
</script>