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>
|
||
```
|