-
-
Notifications
You must be signed in to change notification settings - Fork 2
9.7.6 Components
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.
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: {}
});
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 thetemplate
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 typetext/x-template
to encapsulate the template markup in the HTMLbody
.<!-- 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.
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.
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
are defined in the script of a child component. For example, a component that displays a message that is passed from the parent needs themessage
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 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>
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