Vue.js Introduction: Components
Published: 2020-08-31 01:01:02

###Introduction to Vue.js
Vue.js is a lightweight MVVM framework created by Evan You and released in 2014. It is a ‘component based framework’. This definition refers to the structure of a Vue.js app wherein nested components pass data between each other to achieve the functionality of the application. In this introduction we will understand how to create and import basic components, how the 'template' section of a component works, and how to use the v-bind, v-for and v-on directives. In the next article, we will understand how the 'script' section of a component works, how the v-model directive works, how to use the ‘$emit’ method to render and pass data, and how to use the ‘mounted’ lifecycle. First up, the Vue component. 

### About The Example App
The app in the example is very simple and is comprised of just two Vue.js components, App.vue and PlantSearch.vue. The App.vue renders a PlantSearch component within its template, which captures user search input. On submit, the searchPlant function is called which sends a request to our express server, which which sends back an array of plant objects from the trefle.io API. These are in turn rendered in the App.vue template.

###Components in Vue
By convention, Vue.js files and components are named according to PascalCase, with the initial letter of each word being capitalized. Single-file components are made up of three parts in Vue.js; the template, the script and the style. The example I will use is from our PlantSearch component in the PlantSearch.vue file. We will learn more about the functionality of the PlantSearch component below. For now, we just want to illustrate the component’s most basic essential features.

```javascript
<template>
  <div class="search">
    <form @submit.prevent="handleSubmit">
      <label>Search A Plant</label>
      <input v-model="plant"/>
      <button>Submit Search</button>
    </form>
  </div>
</template>

<script>
  export default {
    name: 'plant-search',
    data () {
      return {
        plant: ''
      }
    },
    methods: {
      handleSubmit(){
        this.$emit('search:plant', this.plant);
      }
    }
  }
</script>
<style>
  .search {
    color: blue
  }

</style>
```

The template comes first and contains some HTML, in particular, a search form. When the component is rendered, this is what will be displayed. In between the script tags, we have our export statement which in this case contains the component’s export name, data (similar to state in React.js), and a handleSubmit method in the ‘methods’ object. Inside the script tags is where most of the JavaScript goes down. This will become apparent when we view the App component a little later on. 
The final part of our single-page PlantSearch component is the style tag. This is where we put the CSS pertaining to our template elements. In this case, we have given a rather simple directive to make the text blue. 

###Attaching Components to the DOM
At least one of our single-file components must be attached to a root-instance of Vue.js. This root-instance is in turn attached to a DOM element in the index.html. In our example, the root-instance, declared in the index.js file

```javascript
import Vue from 'vue'
import App from './app.vue'

new Vue({
  el: '#app',
  render: create => create(App),
})
```

attaches itself to the DOM element with id ‘app’ in the index.html.   This is specified by with the value given to the key 'el' in the options object given to new Vue. This file imports and and the root instance renders our first component, called App, which in turn renders the aforementioned PlantSearch component. Let’s take a look at the App.vue file.

Given the App.vue file is fairly long, we will present it by section; ‘template’ followed by ‘script’ followed by ‘style’, for the sake of readability. 

###App.vue: Template
```javascript
<template>
  <div class="divclass">
    <plant-search v-on:search:plant="searchPlant"/>
    <ul v-for="(p, index) in plants" v-bind:key="index">
      <div>
      <li>{{p.common_name}}</li>
          <div>
            {{p.scientific_name}}
          </div>
          <img v-bind:src="p.image_url"/>
      </div>
    </ul>
  </div>
</template>
```

Here we are introduced to our first directives, v-on, v-for, v-bind. 
###v-on
v-on is a directive that listens for DOM events and runs JavaScript when they happen. In this case, v-on is found in the plant-search component which we have imported and rendered in the App.vue template. When a search is submitted, the corresponding method searchPlant, found in the App.vue script section, is run. The exact way that the plant-search component passes the data to searchPlant has to do with the $emit method found in PlantSearch and will be discussed in the next article. The syntax,
```javascript
v-on:search:plant="searchPlant"
```
is v-on followed by the exported handleSubmit function name from PlantSearch 'search:plant', followed by the function in App.vue, searchPlant, that we want to run when search is submitted.
###v-for
v-for is roughly equivalent to a Vue.js version of a loop. When using v-for in a parent template element, the values can be passed to any of the child elements, as we see above. The syntax is
```javascript
v-for="(p, index) in plants"
``` 
where 'p in plants' refers to each plant in our 'plants' array found below in the 'script' section. v-for can also provide an extra second parameter index, just like in the native map function. This helps us v-bind a unique key for each entry. With v-for, a unique plant entry is created and rendered to the DOM for every plant in the 'plants' array.

###v-bind
v-bind binds a style or a class to whichever element it is called on. In the above template, we v-bind a unique key to each plant rendered


```javascript
<script>
import axios from 'axios';
import PlantSearch from './components/PlantSearch.vue'

const API_URL = "http://localhost:8000/";

export default {
  name: "App",
  components: {
    PlantSearch,
  },
  data: function () {
    return {
      plants: []
    };
  },
  mounted() {
    axios.get(API_URL).then((plantInfo) => {
      this.plants = plantInfo.data;
    }).catch(err => console.log(err));
  },
  methods: {
    searchPlant(plant){
      axios.get("http://localhost:8000/search", {
        params: plant
      }).then((plantInfo) => {
        this.plants = plantInfo.data
      })
    }
  }
};
</script>
```
###Conclusion
Next week, we will go in-depth on the specifics of the 'script' section of our App.vue. We will understand the 'data' function and how data is updated as well as how it is passed between the PlantSearch and App components. For now, we have gained a basic understanding of single-file components and a few essential directives.