Skip to content

9.7.6 Components

DA edited this page Apr 27, 2020 · 15 revisions

Vue provides powerful ways of defining and using components in order to make it easier to integrate with different technologies. The basic way is to have all the components defined in one file. This technique is more than acceptable for small scale applications that have a limited and a predictable set of components. For larger scale applications, Vue offers the capability of creating Single File Components (SFC). We will discover more about SFC in further readings.

The Vue official documentation explains the concepts of components thoroughly. We recommend that you go through the basic concepts behind the components.

Learn more about Vue - Components Basics

In this section, we will focuse primarily on explaining how components are defined and in exploring the different parts and properties of components.

Component Properties

Vue components are reusable instances with their own set of Vue properties: data, methods, computed, watch, mounted etc.

On top of the typical properties, they also present a set of properties of their own: template, props, events, slots.

// Component Structure

Vue.component('component-name', {
	template: '#templateReference', // alternatively the entire markup can be defined in the property
	props: ['propName'],
        data() {
            return {
            }
        },
        computed: {},
        methods: {},
        mounted() {},
        watch: {}

});

Component Templates

Every component has a template. The template is the HTML markup definition of how the component is structured. The template can be placed in different places.

  • script file: The template can be placed directly in the script file within the template property. Notice how the markup is enclosed in "`".

        Vue.component('component-name', {
        props: ['propName'],
        template: 
        `
            <input
            v-bind:value="value"
            v-on:input="$emit('input', $event.target.value)"
            >
        `
        })

    Such a technique combines different languages (javascript and html) into one code and does not necessarily respect the separation of concerns.


  • markup file - Recommended: The more desirable option would be to have the component template in the markup itself thus respecting the separation of concerns and making it easier to have all the markup in one place.

    In order to do that, Vue makes use of the script HTML element with a special type text/x-template to encapsulate the template markup in the HTML body.

        <!-- TEMPLATES FOR VUE COMPONENTS -->
    	
        <script type='text/x-template' id='templateReference'>
            <div>
                <!-- code here -->
            </div>	
        </script>

    Notice

    We now could use the id of the script to reference it in the template property of the component as opposed to putting the whole markup code in it.

Component Communication

Organized components need to transfer information among each other. Depending on the relationship between components (parent or child), the way the information is transferred vary.

Passing data from parents to children

When a component is included in another component, it is the child component. In many instances, the parent component (the component containing the child) needs to pass data to the child component. The data is passed down through props and slots

Learn more about Vue Props and Vue Slots on the Vue official documentation


Props

  • props are defined in the script of a child component. For example, a component that displays a message that is passed from the parent needs the message to be specified as a prop in its script. Here is an example of how the code could look like.

        Vue.component('show-message', {
        template: '#messageBlock', // alternatively the entire markup can be defined in the property
        props: ['message']
        });
  • props are assigned a value to be passed on to the child in the parent component upon use. Here is an example of how the code could look like.

    <body>	
        <div id='app'>
           <show-message message='Welcome to Caligrafy'></show-message>
        </div>
    
        <!-- template definition -->
        <script type='text/x-template' id='messageBlock'>
            <div>
                {{ message }}
            </div>	
        </script>
    </body>
  • props values can be assigned in a hard-coded way as we have seen in the previous point. They could also be passed dynamically by binding the prop to a variable defined in the parent's data properties.

    <body>	
        <div id='app'>
           <show-message :message='welcomeMessage'></show-message>
        </div>
    
        <!-- template definition -->
        <script type='text/x-template' id='messageBlock'>
            <div>
                {{ message }}
            </div>	
        </script>
    </body>

Slots

Slots are another way for a parent to pass data to a child component. Both props and slots achieve the same thing.

slots are defined as a markup in the template of a component. They literally insert an HTML slot into the template and that slot is filled with information coming from the parent.

    <body>	
        <div id='app'>
           <show-message>
               <!-- if only one slot -->
               <slot>{{ welcomeMessage }}</slot>

               <!-- if mutliple slots with different names -->
               <template v-slot:'welcome'>{{ welcomeMessage }}</template>

           </show-message>
        </div>

        <!-- template definition -->
        <script type='text/x-template' id='messageBlock'>
            <div>
                <!-- if only one slot -->
                <slot></slot>

                <!-- if mutliple slots with different names -->
                <slot name='welcome'></slot>
            </div>	
        </script>
    </body>

Triggering events from children to parents

A child component communicates with its parent by triggering an event. The event is captured by the parent in the usage and the event is triggered by the child from its template

    <body>	
        <!-- Parent usage - the showMessage method is defined in the parent's script -->
        <div id='app'>
           <show-message @display-message='showMessage($event)'></show-message>
        </div>

        <!-- Child trigger from the template -->
        <script type='text/x-template' id='messageBlock'>
	    <div class='horizontal-center'>
	        <button @click="$emit('display-message','Welcome to Caligrafy')">Welcome</button>
	    </div>	
        </script>
    </body>



This the end of this basic chapter about the Caligrafy and Vue integration. We encourage you to read the advanced integration for larger scale applications

Clone this wiki locally