131 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
---
 | 
						||
title: Components
 | 
						||
---
 | 
						||
 | 
						||
## Components
 | 
						||
 | 
						||
A classic problem that web developers face is having to write loads and loads of HTML, CSS, and JavaScript to make repeated sections of the website work properly. For example, a set of image carousels that are spaced at various points down the page, each with a different number of images to show.
 | 
						||
 | 
						||
Sometimes all you want is a quick way to be able to use the same code in several different places at once and for everything to just work. Well, Vue.js gives you this ability with Components.
 | 
						||
 | 
						||
Suppose you're developing a landing page for your company's product and you need to display the 4 main features of it following the same structure of a card-like object, with a icon, a title, and a short description.
 | 
						||
 | 
						||
Let's make a component for that:
 | 
						||
 | 
						||
```javascript
 | 
						||
Vue.component('feature-card', {
 | 
						||
  props: ["iconSrc", "iconAltText", "featureTitle", "featureDescription"],
 | 
						||
  template: `
 | 
						||
    <div class="card">
 | 
						||
      <div class="icon-wrapper">
 | 
						||
        <img
 | 
						||
          class="icon"
 | 
						||
          :src="iconSrc"
 | 
						||
          :alt="iconAltText">
 | 
						||
      </div>
 | 
						||
      <h4 class="title">
 | 
						||
        {{ featureTitle }}
 | 
						||
      </h4>
 | 
						||
      <p class="description">
 | 
						||
        {{ featureDescription }}
 | 
						||
      </p>
 | 
						||
    </div>
 | 
						||
  `
 | 
						||
});
 | 
						||
```
 | 
						||
 | 
						||
> Note that here we bound the image `src` attribute with another syntax `:src`.
 | 
						||
This changes nothing, it is simply syntactic sugar (simpler and cleaner syntax) for `v-bind:src` -- whenever
 | 
						||
you want to bind a component attribute to a variable, you can prepend a `:` to the
 | 
						||
attribute name instead of using the full form `v-bind`.
 | 
						||
 | 
						||
With this code, we did a lot of new things:
 | 
						||
 | 
						||
* we created a new component called `feature-card`
 | 
						||
* we defined the `feature-card` component's default **structure** with the `template` attribute
 | 
						||
* we defined a list of properties that the component accepts with the `props`
 | 
						||
  list
 | 
						||
 | 
						||
After defining a component, whenever we desire to reuse it on our web page, we can do so as a kind of 'custom' html element. In our example, we can use the tag `<feature-card>`, which is the component's name wrapped in < and >:
 | 
						||
 | 
						||
```html
 | 
						||
<div id="app">
 | 
						||
  <feature-card
 | 
						||
    iconSrc="https://freedesignfile.com/upload/2017/08/rocket-icon-vector.png"
 | 
						||
    iconAltText="rocket"
 | 
						||
    featureTitle="Processing speed"
 | 
						||
    featureDescription="Our solution has astonishing benchmarks grades">
 | 
						||
  </feature-card>
 | 
						||
</div>
 | 
						||
```
 | 
						||
 | 
						||
In this case, we called the `<feature-card>` as it was an existing tag, as well as set the `iconSrc` or `featureTitle` as they were valid attributes. The purpose of Vue.js components is to increment your toolbox with your own tools.
 | 
						||
 | 
						||
If you're lost, here is what the outputted html from the example above would look like:
 | 
						||
 | 
						||
```html
 | 
						||
<div id="app">
 | 
						||
  <div class="card">
 | 
						||
      <div class="icon-wrapper">
 | 
						||
        <img class="icon" src="https://freedesignfile.com/upload/2017/08/rocket-icon-vector.png" alt="rocket"/>
 | 
						||
      </div>
 | 
						||
      <h4 class="title">Processing speed</h4>
 | 
						||
      <p class="description">Our solution has astonishing benchmarks grades</p>
 | 
						||
    </div>
 | 
						||
</div>
 | 
						||
```
 | 
						||
 | 
						||
The purpose of Vue.js components is this: expand your web page building toolbox with your own shiny new tools
 | 
						||
 | 
						||
### Props
 | 
						||
 | 
						||
Props, as mentioned above, are custom attributes you can register on a component. When a value is passed to a prop attribute, it becomes a property on that component instance. To pass a title to our blog post component, we can include it in the list of props the component accepts, using the props option:
 | 
						||
 | 
						||
```js
 | 
						||
Vue.component('feature-card', {
 | 
						||
  props: ['title'],
 | 
						||
  template: '<h3>{{ title }}</h3>'
 | 
						||
})
 | 
						||
```
 | 
						||
 | 
						||
A component can have as many props as you’d like and by default and _any value_ can be passed to _any prop_. In the template above, you’ll see that we can access this value on the component instance, just like with data.
 | 
						||
 | 
						||
>As mentioned above, because any value can be passed into a prop, it's often a good idea to validate the correct data is being passed in. You can do this in a few different ways, including [Vue's built in Prop Validation](https://vuejs.org/v2/guide/components-props.html#Prop-Validation "Prop validation on the Vue website")
 | 
						||
 | 
						||
Once a prop is registered, you can pass data to it as a custom attribute, like this:
 | 
						||
 | 
						||
```html
 | 
						||
<blog-post title="My journey with Vue"></blog-post>
 | 
						||
<blog-post title="Blogging with Vue"></blog-post>
 | 
						||
<blog-post title="Why Vue is so fun"></blog-post>
 | 
						||
```
 | 
						||
 | 
						||
### Single File Components
 | 
						||
 | 
						||
Instead of declaring many components in a single file resulting in a long spaghetti code. You may want to modularize your components by having different files. (ie. more info: [Single File Components](https://vuejs.org/v2/guide/single-file-components.html))
 | 
						||
 | 
						||
Enclose your template in a `<template>` tag, script the structure of the component in the `<script>` tag and style your components in the `<style scoped>` tag.
 | 
						||
 | 
						||
```html
 | 
						||
<template>
 | 
						||
  <p>{{ greeting }} World!</p>
 | 
						||
</template>
 | 
						||
 | 
						||
<script>
 | 
						||
module.exports = {
 | 
						||
  data: function () {
 | 
						||
    return {
 | 
						||
      greeting: 'Hello'
 | 
						||
    }
 | 
						||
  }
 | 
						||
}
 | 
						||
</script>
 | 
						||
 | 
						||
<style scoped>
 | 
						||
p {
 | 
						||
  font-size: 2em;
 | 
						||
  text-align: center;
 | 
						||
}
 | 
						||
</style>
 | 
						||
```
 |