This lab corresponds to the section Component Basics of the VueSchool course Vue.js Components Fundamentals
This repository contains only the example codes for
- The click counter (video Introduction to Components) and
- plan-picker
examples used inside the initial section of the tutorial Component Basics.
The goal is to write a simple component <click-counter>that can be called like that:
<div id="app">
<h1>Vue.js Components Fundamentals</h1>
<click-counter></click-counter>
<click-counter></click-counter>
<click-counter></click-counter>
<click-counter></click-counter>
</div>so that when you click in the input the counter shown is increased. The code above has to work as shown here: https://crguezl.github.io/vuejs-components-basics-plan-picker-component/click-counter/solution.html
Watch the videos
And write your code inside the empty files index.html and app.js.
Files click-counter/solution.html and click-counter/solution-app.js contain the final solution.
├── app.js
├── index.html
├── solution-app.js
└── solution.html
-
All along, use as many emmet expressions as you can to speed up the edition
-
Set the initial HTML and load Vue from the CDN
-
Inside the app create the Vue app attached to the corresponding div element
-
Create a component
click-counterusingVue.component- Add the
datafunction that returns the object with the data. - Set the
count - In the template add the
v-onto increase the counter each time the button is clicked
- Add the
-
Add in the
appdiv of the HTML the component just created -
Insert new instances of the component in the HTML
-
Move the template from the
app.jsto the HTML using ascripttag -
Instead of
<script type= 'text/x-template' ...>try also to use the<template>HTML tag. Does it works? -
Add a second element, a paragraph
the count isto theclick-countercomponent -
Wrap the two elements in a
<div> -
Move all the code from
app.jsto the HTMLindex.html -
Add a
propwith nameclick-titleto theclick-countercomponent so that instead of the fixed"the count is", the parent component can specify the prefix paragraph:<click-counter click-title="The first counter is:"></click-counter> <click-counter click-title="The second counter is:"></click-counter> <click-counter click-title="The Third counter is:"></click-counter>
Read the section Prop Casing (camelCase vs kebab-case) of the Annotated Reading of the Essentials Section of the Vue.js Guide
In this exercise you have to start from a HTML file that contains repeated <div class="plan"> like
<div class="plans">
<div class="plan">
<div class="description">
<span class="title">
The Single
</span>
</div>
</div>
<div class="plan">
<div class="description">
<span class="title">
The Addict
</span>
</div>
</div>
...
</div> and you have to factorize the code introducing a Vue.js component <plan>
Watch the videos
- Reusable Components with Props 6:46
- Nested Components 1:50
- Global vs Local Components 3:11
- Communication Between Components with Custom Events 7:24
Leave your solution inside the files index.html and app.js.
Here is the structure of the folder:
├── coffee.jpg
├── index.html
├── logo.png
├── solution-app.js
├── solution.html
└── style.css
Files plan-picker/solution.html and plan-picker/solution-app.js contain the final solution.
See the solution working at https://crguezl.github.io/vuejs-components-basics-plan-picker-component/plan-picker/solution.html
-
Use a minimum number of emmet expressions to generate complete the initial
index.htmlto have it as at the beginning of the video Reusable Components with Props. The structure to replicate three or four times has to follow this pattern:<div class="plans"> <div class="plan"> <div class="description"> <span class="title"> The Single </span> </div> </div> ... more like the one above </div>
- Here is a solution
-
Load Vue from the CDN and add the main app
-
Create the
plancomponent that encapsulates the template above -
Add it the
propwith thename, interpolate it inside the component template and update the calls in the HTML accordingly for all the repetitions -
Add to the Vue app data the
plansarray of Strings with the names of the plans -
Substitute the repetitions of the
<plan>component inside the HTML for av-forloop -
Specify that the
propnamehas to be of typeStringand isrequired
Nested Components Video
- Create a component with name
<plan-picker>to encapsulate the.plansdiv - Create the template for the component and move the
plansarray into the component
- Make the
plancomponent local to theplan-pickercomponent- Check that a local component can not be used out of its scope
- Make the
plan-pickercomponent local to the root component- Register first the component with the name
planPickerand try to use it. What happens? - Change the name to
plan-picker
- Register first the component with the name
We want to add the capability to select a plan. See how the solution works when you click in one of the plans. We want to reproduce this behavior,
-
Add a boolean variable
selectedto theplancomponent -
Add a
selectmethod to theplancomponent to set the component as selected -
Add the code so that when a user clicks on the root element of the
plancomponent template theselectmethod is called- See Event Handling and Component Custom Events in the Vue.js Guide
- What happens if you add the code for the click on an element inside the
plancomponent?
-
Using the object syntax for
v-bindadd a classactive-planwhen aplancomponent is selected so that the background color of the button changes when selected, since thestyle.csscontains the following:.plans .active-plan { border-color: #352001; background-image: linear-gradient(to bottom right, white, #8F4401); }
See Class and Style Bindings in the Vue.js Guide
-
Verify that, unfortunately, the solution given permits several plans to be selected
-
We need to let the component communicate to its parent when the user has clicked on it. Make the
plancomponent to$emitan event with nameselectand payload thenameof the plan- Read the notes on the api of vm.$emit( eventName, […args] )
-
Check in the event tab of the Vue DevTools the presence of the events generated when you click
-
Inside the
plan-pickercomponent template set the triggering of a methodselectPlanto fire when theselectevent is emitted. -
Inside the
plan-pickercomponent add a data attributeselectedPlanto store the plan that was selected by the user -
Add also the code for the
selectPlanmethod -
The idea is now that the parent
plan-pickercomponent will send the selected plan as a property to the children components.Go back to the
plancomponent and remove theselecteddata property (it is no longer need, since the parent component now knows which plan has been selected) -
Add a property
selectedPlanto theplancomponent (that will be passed by the parent) -
Add a computed property
isSelectedto theplancomponent that istruewhen the plan is the one selected -
In the template of the
plancomponent conditionally bind the classactive-planto the.plandiv if the plan is selected -
Inside the
plan-picker-templatepass the propertyselectedPlanto the children.- Be carefull that HTML attributes are case insensitive but the name of the
planattribute we choose inside the JavaScript code wasselectedPlan(CamelCase) and so to writev-bind:selectedPlan="..."is not going to work. You have to use the equivalent kebab-case string
- Be carefull that HTML attributes are case insensitive but the name of the
After this lab, you'll be familiar with:
- The idea behind components and how Vue.js components work
- Component's template, and couple of ways to define your template
- Communication between components with props and custom events
- What is the difference between global and local component registration