Vue.js Basics: components

10th Jul 19
blossom

I will cover more of the basics with Vue components.

Component

You firstly need to register a component, importing Vue and the component file.

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

new Vue({
  render: h => h(App),
}).$mount('#app')

Then the component content needs to be wrapped in a <template> tag and have a root div.

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

Components can hold child components such as HelloWord seen above.

Sending data through props

  <HelloWorld v-bind:prop='message'/>

...

 data: () =>({
    message: 'hello'
  })

In helloworld component: 


...
props: ['prop']

/*and outputting it */

  <p>{{prop}}</p>

returns 'hello'.

Using props data and sending data out

The props in the component is accessible in its data and methods.  For sending data from the component to its parent component you first need to pass the data to its component tag by using the $emit method.  The $emit method accepts one or more arguments.  The first argument is the name of the self defined event.  The following arguments are data to be sent with the self defined event.  

In the component I bind the self-defined method with the v:on directive.  

In HelloWorld component I have a input and a button: 

 <input type="text" v-model='message'>
 <button v-on:click='send'>Send Message</button>

The button is bound to the 'send' method.

  data: () => ({
    message: 'take me to my leader',
  }),

  methods: {
    send: function(){
      this.$emit('relay', this.message)
    }
  },

In the parent component:

 <HelloWorld v-on:relay='content=arguments[0]' />
  <h3>{{content}}</h3>

The parent component data: 

  data: () =>({
    content: 'waiting for content'
  })

.. is updated from the child component with a click of a button.

Communication between sibling components

For two sibling components to communicate with each other you can use an event bus.  The event bus uses the $emit and $on methods.  The $emit method is used to trigger a self defined event, sending data to that event.  The $on method is for monitoring the self defined event and receiving the data.  The emit method is for sending data out of the component, and on method for receiving the data in a sibling component.  

The $on method takes two arguments, the first is the self defined event.  The second argument is an anonymous function where is takes an argument that represents that data sent from the $emit method.  Then in the anonymous function we can bind the received data to the corresponding data.

firstly I create a javascript file named event-bus.js:

import Vue from 'vue';
export const EventBus = new Vue();

I import it into both the HelloWorld component and the child component.

import { EventBus } from '../event-bus.js';

In the HelloWorld component: 

    <input type="text" v-model='message'>
    <button v-on:click='send'>Send Message</button>
export default {
  data: () => ({
    message: 'send a message to my sibling',
  }),

  methods: {
    send: function(){
      this.$emit('relay', this.message);
      EventBus.$emit('to_child', this.message);
    }
  },

In Chlid component I add the listener ($on method) in the created hook:

   created: function(v){
        EventBus.$on('to_child', function(v){
            alert(v);
        })
    }

With 'v' being the 'message' from HelloWorld component.

To assign the received data to its component data, you have to bind 'this' to the anonymous function: 

    created: function(v){     
        EventBus.$on('to_child', function(v){       
            this.message_child = v;
        }.bind(this))
    }

 

Sync Modifier

The sync modifier provides a two way binding for a prop. In my example HelloWorld component has input where it will send data to the App Component content data.  When the app is loaded for the first time, the data will be the 'content' data from App.  

In App.vue: 

   <h3>{{content}}</h3>
    <HelloWorld v-bind:value.sync='content' />
 data: () =>({
    content: 'original data'
  })

with value being the prop in HelloWorld

In HelloWorld: 

 <input v-bind:value='value' type="text" v-on:input='send($event.target.value)'>
 methods: {
    send: function(v){
      this.$emit('update:value', v);

    }
  },
  props: ['value']

Note that the self-defined event should always be named update.  Now the data is synced without having to click a button.

I have recently completed my apprenticeship.  I am currently building the API to a React JS site using Firebase.