Vue.js Events - $emit

If you're just getting started with this series of Vue.js posts, you should start with the Vue.js Starter Page.

Vue.js uses events to pass data from a child component up to a parent component, specifically calling the event $emit. Here's how:

Vue.js Events (via $emit)

This file is actually a combination of 2 different Vue files; App.vue (the parent component) and Header.vue (the child component).

In a recent discussion comparing Primitive vs. Reference Types, string data altered in the Vue.js framework (primitive) is changed directly in the component and affects only the variable in that specific component where the change was made. Changes made to data sets, like arrays (reference types) affect all instances in all components. So in order to make primitive data behave and update just like reference types, Vue.js uses events ($emit) to broadcast changes UP from a child component to a parent component that is prepared to listen for such changes.

Line 6 shows the child component's v-on:click that will trigger the method changeTitle - also in the child component - on line 24. This function changeTitle() uses $emit to broadcast the event also named changeTitle up to the parent component (App.vue) where a listener has been setup via a v-on:changeTitle on line 44. When received, the updateTitle method on line 78 accepts the passed argument (here it's the event object $event). We arbitrarily refer to the passed argument in this method as updatedTitle causing the method to fire and complete.

<!--Header.vue template-->
<!-- thanks to https://www.youtube.com/watch?v=6-us2D7GQCk&list=PL4cUxeGkcC9gQcYgjhBoeQH7wiAyZNrYa&index=21 -->

<template>
	<header>
		<h1 v-on:click="changeTitle">{{title}}</h1>
	</header>
</template>


<script>
	export default {
		props:{
			title:{
				type:String
			}
		},
		data(){
			return{
				title:'Vue Ninjas'
			}
		},
		methods(){
			changeTitle:function(){
				this.$emit(changeTitle,'My latest title');
			}
		}
	}
</script>

<!-- add "scoped" attribute to style tag to ensure that only elements in this component get style applied, else it goes global -->
<style scoped>

</style>


<!-- end Header.vue-->


<!-- start App.vue-->

<template>
  <div>
    <app-header v-bind:title="title" v-on:changeTitle="updateTitle($event)"></app-header>
	<app-muscles></app-muscles>
	<app-footer v-bind:title="title"></app-footer>
  </div>
</template>

<script>

	import Header from './components/Header.vue';
	import Footer from './components/Footer.vue';
	import Muscles from './components/Muscle.vue';

export default {
	  components{
		'app-header':Header;
		'app-footer':Footer;
		'app-muscles':Muscles;
	  },
  
  name: 'app',
  data () {
    return {
      muscles:[
			{name: 'Pectoralis', area:'Chest', show:false},
			{name: 'Biceps', area:'Arm', show:false},
			{name: 'Triceps', area:'Arm', show:false},
			{name: 'Latissimus', area:'Back', show:false},
			{name: 'Quadriceps', area:'Leg', show:false},
			{name: 'Soleus', area:'Calf', show:false}
		],
   		title:"Muscle Title Here"
    }
  },
  methods:{
  	updateTitle(updatedTitle){
  		this.title=updatedTitle;
  	}
  }
}
</script>

<style>
	#app {
	  font-family: 'Avenir', Helvetica, Arial, sans-serif;
	  -webkit-font-smoothing: antialiased;
	  -moz-osx-font-smoothing: grayscale;
	  text-align: center;
	  color: #2c3e50;
	  margin-top: 60px;
	}

	h1, h2 {
	  font-weight: normal;
	}

	ul {
	  list-style-type: none;
	  padding: 0;
	}

	li {
	  display: inline-block;
	  margin: 0 10px;
	}

	a {
	  color: #42b983;
	}
	</style>

	<!-- end App.vue-->



Link your website to this page! Copy and paste the URL below:
http://www.cfsnap.com/vue-js/vue-js-events-emit/