<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Vuex - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Vuex - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 24 Jun 2026 17:36:28 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/vuex/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Learn Vuex in 5 minutes ]]>
                </title>
                <description>
                    <![CDATA[ By Per Harald Borgen This tutorial will give you a basic understanding of Vuex by building a plan-making application. A user can type in activities and then vote how much they like/dislike them. Once you've read this tutorial, you can check out our f... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-vuex-in-5-minutes/</link>
                <guid isPermaLink="false">66d852578acc348be2a441d0</guid>
                
                    <category>
                        <![CDATA[ vue ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Vuex ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 28 May 2020 20:37:58 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/05/learn-vuex.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Per Harald Borgen</p>
<p>This tutorial will give you a basic understanding of Vuex by building a plan-making application. A user can type in activities and then vote how much they like/dislike them.</p>
<p>Once you've read this tutorial, you can check out our <a target="_blank" href="https://scrimba.com/g/gvuex">free Vuex course on Scrimba</a>, if you're interested in learning more.</p>
<p>What is Vuex? From <a target="_blank" href="https://vuex.vuejs.org">Vue's official documentation</a></p>
<pre><code>Vuex is a state management pattern + library <span class="hljs-keyword">for</span> Vue.js applications.
It serves <span class="hljs-keyword">as</span> a centralized store <span class="hljs-keyword">for</span> all the components <span class="hljs-keyword">in</span> an application, <span class="hljs-keyword">with</span> rules ensuring that the state can only be mutated <span class="hljs-keyword">in</span> a predictable fashion.
</code></pre><p>This course assumes that you're somewhat familiar with Vue and we will briefly touch on features like <code>props</code>, components and bindings, but will not review them in great detail. If you'd like to have a quick primer on Vue, feel free to <a target="_blank" href="https://scrimba.com/p/pXKqta">check out this course on Scrimba</a>.</p>
<h1 id="heading-the-setup">The setup</h1>
<p>At Scrimba, complicated setups are something we just don't do.<br>For this tutorial, we've created a simple HTML file where everything can be written. Feel free to write your own CSS or just copy it from <a target="_blank" href="https://scrimba.com/c/c66qG4uG">this playground</a></p>
<p>Vue and Vuex libraries are imported via CDN using <code>&lt;script&gt;</code> tags:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Activity Voter<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/vue/dist/vue.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/vuex/dist/vuex.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
      <span class="hljs-comment">/*
        ADD CSS HERE
      */</span>
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-comment">/*
      ADD VUE CODE HERE
    */</span>
  </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Alternatively, you can also experiment with the code in <a target="_blank" href="https://scrimba.com/c/cqRNMEcG">this Vue Scrimba playground</a> Just remember to <strong>relink the playground to your own account.</strong></p>
<h1 id="heading-app-plan">App plan</h1>
<p>We're going to build a voting app, that works especially well when you're in a group of friends not knowing what to do and you have to consider all the options.</p>
<p>The functionality will consist of a user being able to type in an activity and then each activity will have a vote up and down button to count up the totals.</p>
<h1 id="heading-getting-started">Getting started</h1>
<p>First, let's quickly mock our app up in HTML. We will use this layout to then extract into a separate component and we will add functionality for the layout to come to life.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Activity voter<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Add Activity"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"button"</span>&gt;</span>Add Activity<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>
Go Snowboarding<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>?<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>?<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        5
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>?<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/42ixhwdzkncbibp1m210.png" alt="Image" width="882" height="522" loading="lazy"></p>
<h1 id="heading-add-vuex-store-with-some-basic-data">Add Vuex store with some basic data</h1>
<p>Vuex starts with the store. The store is where we keep (store) our state.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  Vue.use(Vuex);

  <span class="hljs-keyword">const</span> store = <span class="hljs-keyword">new</span> Vuex.Store({

  });

  <span class="hljs-keyword">new</span> Vue({
    <span class="hljs-attr">el</span>: <span class="hljs-string">"#app"</span>,
    store
  });
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>Let's also add some hard-coded data to the store, that will include one activity and an array with one emoji to display our feelings towards the activity.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  Vue.use(Vuex);

  <span class="hljs-keyword">const</span> store = <span class="hljs-keyword">new</span> Vuex.Store({
    <span class="hljs-attr">state</span>: {
      <span class="hljs-attr">activities</span>: [{ <span class="hljs-attr">name</span>: <span class="hljs-string">"go snowboarding"</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">5</span> }],
      <span class="hljs-attr">emojis</span>: [<span class="hljs-string">"?"</span>]
    }
  });

  <span class="hljs-keyword">new</span> Vue({
    <span class="hljs-attr">el</span>: <span class="hljs-string">"#app"</span>,
    store
  });
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>To allow our state to change reactively, we can use Vuex <code>mapState</code> to handle computed state properties for us.</p>
<pre><code class="lang-js">  <span class="hljs-keyword">new</span> Vue({
    <span class="hljs-attr">el</span>: <span class="hljs-string">"#app"</span>,
    store,
    <span class="hljs-attr">computed</span>: Vuex.mapState([<span class="hljs-string">"activities"</span>, <span class="hljs-string">"emojis"</span>])
  });
</code></pre>
<h1 id="heading-add-component">Add component</h1>
<p>Now we have activities inside our state. Let's render a separate component for each of those activities. Each one will need <code>activity</code> and <code>emojis</code> props.</p>
<pre><code class="lang-js">Vue.component(<span class="hljs-string">"activity-item"</span>, {
  <span class="hljs-attr">props</span>: [<span class="hljs-string">"activity"</span>, <span class="hljs-string">"emojis"</span>],
  <span class="hljs-attr">template</span>: <span class="hljs-string">`
    &lt;li&gt;
      &lt;span&gt;{{ activity.name }}
        &lt;span&gt;{{ emojis[0] }}&lt;/span&gt;
        &lt;button&gt;?&lt;/button&gt;
        {{activity.rating}}
        &lt;button&gt;?&lt;/button&gt;
      &lt;/span&gt;
    &lt;/li&gt;
    `</span>
});
</code></pre>
<p>Inside <code>app</code> we can now use our newly created component with all the appropriate bindings for <code>activity</code> and emojis. As a quick reminder, if we want to loop over an array and display a component for each item in an array, in Vue, we can use <code>v-for</code> binding.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Activity voter<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Add Activity"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"button"</span>&gt;</span>Add Activity<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">activity-item</span>
      <span class="hljs-attr">v-for</span>=<span class="hljs-string">"item in activities"</span>
      <span class="hljs-attr">v-bind:activity</span>=<span class="hljs-string">"item"</span>
      <span class="hljs-attr">v-bind:emojis</span>=<span class="hljs-string">"emojis"</span>
      <span class="hljs-attr">v-bind:key</span>=<span class="hljs-string">"item.name"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">activity-item</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/42ixhwdzkncbibp1m210.png" alt="Image" width="882" height="522" loading="lazy"></p>
<h1 id="heading-add-mutations-to-store">Add mutations to store</h1>
<p>If we want to update the store in Vuex, we can use mutations. At the moment we will just <code>console.log</code> that a mutation happened and we will implement it afterwards.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> store = <span class="hljs-keyword">new</span> Vuex.Store({
  <span class="hljs-attr">state</span>: {
    <span class="hljs-attr">activities</span>: [
      { <span class="hljs-attr">name</span>: <span class="hljs-string">"go snowboarding"</span>, <span class="hljs-attr">rating</span>: <span class="hljs-number">5</span> },
    ],
    <span class="hljs-attr">emojis</span>: [<span class="hljs-string">"?"</span>]
  },
  <span class="hljs-attr">mutations</span>: {
    increment(state, activityName) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'increment'</span>);
    },
    decrement(state, activityName) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'decrement'</span>);
    },
  }
});
</code></pre>
<p>How do we trigger a mutation? We call a <code>commit</code> function on <code>$store</code> with the name of mutations we want to be executed. Any arguments after the name of a mutation are treated as arguments to a committed mutation.</p>
<pre><code class="lang-js"><span class="hljs-keyword">new</span> Vue({
  <span class="hljs-attr">el</span>: <span class="hljs-string">"#app"</span>,
  store,
  data() {
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">activityName</span>: <span class="hljs-string">""</span>
    };
  },
  <span class="hljs-attr">computed</span>: Vuex.mapState([<span class="hljs-string">"activities"</span>, <span class="hljs-string">"emojis"</span>]),
  <span class="hljs-attr">methods</span>: {
    increment(activityName) {
      <span class="hljs-built_in">this</span>.$store.commit(<span class="hljs-string">"increment"</span>, activityName);
    },
    decrement(activityName) {
      <span class="hljs-built_in">this</span>.$store.commit(<span class="hljs-string">"decrement"</span>, activityName);
    }
  }
});
</code></pre>
<h1 id="heading-add-functionality-to-component">Add functionality to component</h1>
<p>Each <code>activity-item</code> has voting buttons that need to <code>increment</code> and <code>decrement</code> on click of a button. We can pass these functions as props. Let's now bind our methods to props.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">activity-item</span>
  <span class="hljs-attr">v-for</span>=<span class="hljs-string">"item in activities"</span>
  <span class="hljs-attr">v-bind:increment</span>=<span class="hljs-string">"increment"</span>
  <span class="hljs-attr">v-bind:decrement</span>=<span class="hljs-string">"decrement"</span>
  <span class="hljs-attr">v-bind:activity</span>=<span class="hljs-string">"item"</span>
  <span class="hljs-attr">v-bind:emojis</span>=<span class="hljs-string">"emojis"</span>
  <span class="hljs-attr">v-bind:key</span>=<span class="hljs-string">"item.name"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">activity-item</span>&gt;</span>
</code></pre>
<p>Let's also not forget to provide <code>activity.name</code> as an argument to both.</p>
<pre><code class="lang-js">Vue.component(<span class="hljs-string">"activity-item"</span>, {
  <span class="hljs-attr">props</span>: [<span class="hljs-string">"activity"</span>, <span class="hljs-string">"emojis"</span>, <span class="hljs-string">"increment"</span>, <span class="hljs-string">"decrement"</span>],
  <span class="hljs-attr">template</span>: <span class="hljs-string">`
    &lt;li&gt;
      &lt;span&gt;{{ activity.name }}
          &lt;span&gt;{{ emojis[0] }}&lt;/span&gt;
          &lt;button @click="decrement(activity.name)"&gt;?&lt;/button&gt;
          {{activity.rating}}
          &lt;button @click="increment(activity.name)"&gt;?&lt;/button&gt;
      &lt;/span&gt;
    &lt;/li&gt;
    `</span>
});
</code></pre>
<p>And there we go! The flow is working. We can see the <code>console.log</code> statement in the console.  </p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/2spr4ea73npem7pyv05h.png" alt="Image" width="1874" height="359" loading="lazy"></p>
<h1 id="heading-implement-counter">Implement counter</h1>
<p>Let's implement the counter. First, we need to find an activity by its name, and then update its rating.</p>
<pre><code class="lang-js">  mutations: {
    increment(state, activityName) {
      state.activities
        .filter(<span class="hljs-function"><span class="hljs-params">activity</span> =&gt;</span> activity.name === <span class="hljs-string">`<span class="hljs-subst">${activityName}</span>`</span>)
        .map(<span class="hljs-function"><span class="hljs-params">activity</span> =&gt;</span> activity.rating++);
    },
    decrement(state, activityName) {
      state.activities
        .filter(<span class="hljs-function"><span class="hljs-params">activity</span> =&gt;</span> activity.name === <span class="hljs-string">`<span class="hljs-subst">${activityName}</span>`</span>)
        .map(<span class="hljs-function"><span class="hljs-params">activity</span> =&gt;</span> activity.rating--);
    }
  }
</code></pre>
<p>Perfect, we can now vote on activities.  </p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/eh23lvlqaszxq0rxmkel.png" alt="Image" width="900" height="530" loading="lazy"></p>
<h1 id="heading-use-form-input-to-add-activity">Use form input to add activity</h1>
<p>But of course, we need to be able to add activities too.</p>
<p>Let's create a mutation to the store, that would add an activity to the list of existing activities, with a name that we will later get from the input and a default rating of 0.</p>
<pre><code class="lang-js"> mutations: {
    ...
    addActivity(state, name) {
      state.activities.push({ name, <span class="hljs-attr">rating</span>: <span class="hljs-number">0</span> });
    }
  }
</code></pre>
<p>Inside methods, we can commit a new activity to the store.</p>
<pre><code class="lang-js">methods: {
    ...
    addActivity(activityName) {
      <span class="hljs-built_in">this</span>.$store.commit(<span class="hljs-string">"addActivity"</span>, activityName);
    }
  }
</code></pre>
<h1 id="heading-implement-form-submission">Implement form submission</h1>
<p>Let's wire up the submit function to our HTML form.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> @<span class="hljs-attr">submit</span>=<span class="hljs-string">"onSubmit"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Add Activity"</span> <span class="hljs-attr">v-model</span>=<span class="hljs-string">"activityName"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"button"</span>&gt;</span>Add Activity<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>We can now add our submit function to methods. Inside, we're going to use our existing <code>addActivity</code> method and in the end, reset <code>activityName</code> in the input field to an empty string.</p>
<pre><code class="lang-js">methods: {
    ...
    onSubmit(e) {
      e.preventDefault();
      <span class="hljs-built_in">this</span>.addActivity(<span class="hljs-built_in">this</span>.activityName);
      <span class="hljs-built_in">this</span>.activityName = <span class="hljs-string">""</span>;
    }
  }
</code></pre>
<p>We call <code>e.preventDefault()</code> to avoid the form from reloading on each addition of a new activity.</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/qsnc185pcchj71c6878i.png" alt="Image" width="878" height="608" loading="lazy"></p>
<p>All the counters now work and the field gets updated. It does look a bit strange, that we have only one emotion for all the activities, no matter what their rating is.</p>
<p>Let's rewrite emojis into an object with some description of what moods they are meant to reflect and clean up existing state, so we start from no activities.</p>
<pre><code class="lang-js">state: {
    <span class="hljs-attr">activities</span>: [],
    <span class="hljs-attr">emojis</span>: { <span class="hljs-attr">yay</span>: <span class="hljs-string">"?"</span>, <span class="hljs-attr">nice</span>: <span class="hljs-string">"?"</span>, <span class="hljs-attr">meh</span>: <span class="hljs-string">"?"</span>, <span class="hljs-attr">argh</span>: <span class="hljs-string">"?"</span>, <span class="hljs-attr">hateIt</span>: <span class="hljs-string">"?"</span>}
},
...
</code></pre>
<p>And as a finishing touch, we can display different emojis depending on the rating an activity has.</p>
<pre><code class="lang-js">Vue.component(<span class="hljs-string">"activity-item"</span>, {
  <span class="hljs-attr">props</span>: [<span class="hljs-string">"activity"</span>, <span class="hljs-string">"emojis"</span>, <span class="hljs-string">"increment"</span>, <span class="hljs-string">"decrement"</span>],
  <span class="hljs-attr">template</span>: <span class="hljs-string">`
    &lt;li&gt;
      &lt;span&gt;{{ activity.name }}
        &lt;span v-if="activity.rating &lt;= -5"&gt;{{ emojis.hateIt }}&lt;/span&gt;
        &lt;span v-else-if="activity.rating &lt;= -3"&gt;{{ emojis.argh }}&lt;/span&gt;
        &lt;span v-else-if="activity.rating &lt; 3"&gt;{{ emojis.meh }}&lt;/span&gt;
        &lt;span v-else-if="activity.rating &lt; 5"&gt;{{ emojis.nice }}&lt;/span&gt;
        &lt;span v-else&gt;{{ emojis.yay }}&lt;/span&gt;
        &lt;button @click="decrement(activity.name)"&gt;?&lt;/button&gt;
          {{activity.rating}}
        &lt;button @click="increment(activity.name)"&gt;?&lt;/button&gt;
      &lt;/span&gt;
    &lt;/li&gt;
    `</span>
});
</code></pre>
<p>We start with a blank app, which is what we wanted.  </p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/7izt1gxbmnje90fiv9gq.png" alt="Image" width="898" height="432" loading="lazy"></p>
<p>And now if we add back the two activities we used to have in the app, vote on the ratings we have emojis that reflect how we feel about the activities!  </p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/hclj6218rr3pxe5pnv19.png" alt="Image" width="918" height="640" loading="lazy"></p>
<p>You can check out the full code <a target="_blank" href="https://gist.github.com/perborgen/ce11d4f36cfb97f2ddb15ae73bfa10dd">here.</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Top JavaScript Frameworks For Front-End Development in 2020 ]]>
                </title>
                <description>
                    <![CDATA[ By Shifa Martin Front-end developers might know this game already: you type “top JavaScript frameworks” into Google and you get so many JavaScript frameworks from which to choose. There are always more choices for JavaScript frameworks. And it's alwa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/complete-guide-for-front-end-developers-javascript-frameworks-2019/</link>
                <guid isPermaLink="false">66d460f03bc3ab877dae2230</guid>
                
                    <category>
                        <![CDATA[ Angular ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Angular ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[  Single Page Applications  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ vue ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Vue.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Vuex ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 08 Nov 2019 12:45:14 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/11/1181834_8257_2.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Shifa Martin</p>
<p>Front-end developers might know this game already: you type “top JavaScript frameworks” into Google and you get so many JavaScript frameworks from which to choose.</p>
<p>There are always more choices for JavaScript frameworks. And it's always tough to choose a JavaScript framework for front-end development.</p>
<p>So, what are front-end developers looking for in their tech stacks? As a full-time developer, I know it comes down to rapid development and easy-to-make UIs.</p>
<p>Rather than try to be decisive, we, 450+ developers at <a target="_blank" href="https://www.valuecoders.com/">ValueCoders software development company</a>, voted and shortlisted a few of the best JavaScript frameworks.</p>
<h3 id="heading-our-vote-goes-to-react">Our Vote Goes to React</h3>
<p>I was not surprised to see this. Most of our developers voted for React as one of the best JavaScript frameworks. There have been plenty of projects along the way that our front-end developers are handling that highlighted the strengths of the JS framework. React provides a combination of the following:</p>
<ul>
<li>Reusable components</li>
<li>Synchronization of state and view</li>
<li>Routing and template system</li>
</ul>
<p>Our developers implement front-end logic by relying heavily on React. At the same time, I was surprised by how simple it was to create  applications with React.</p>
<h3 id="heading-here-is-an-overview-of-our-app">Here is an Overview of Our App</h3>
<p>The application is simple. It’s a <a target="_blank" href="https://www.valuecoders.com/case-studies/online-music-school">studio management app</a> for music teachers that helps them focus more on their teaching and less on the management of their music studio.</p>
<p>The key challenge was creating one ‘Activity Dashboard’ for teachers where they could manage all their students' activities and track their progress over time. We overcame this challenge by using <a target="_blank" href="https://redux.js.org/introduction/ecosystem">Redux libraries</a> to build the platform. We built a teacher’s studio from where they could manage their students' progress, showcase new music lessons, chat with them, compare students music playing with live music, and provide them feedback.</p>
<p><img src="https://lh3.googleusercontent.com/MlqY_vfvZEVG1w6UKUhasIekmnODKhSBr5MM3WVLVSzS6_rXyi-wq0npVhBqILg1Totwwccloq9XWQwFF-VWpOCtF8vqj7yOmV4tDKJ9vyNM8jg_YJYvt4x6njz51w1-eI9ojzQ6" alt="Image" width="315" height="564" loading="lazy"></p>
<p>So, this is my experience with React JS. But many would argue that Vue is one of the best front-end JavaScript frameworks with many useful tools. </p>
<p>Front-end developers are the ones deciding which JavaScript framework will do the job. In doing so, they face a lot of challenges because they need to decide what they’ve always needed. Often, we have to choose a JavaScript framework now, not after a week of research. In that case, most developers go with what they know. But maybe the stacks you’re familiar with are no longer cutting it in terms of performance.</p>
<p>Even just choosing among Angular, React, an Vue, it is difficult for new developers. Rather than making it more exhaustive for you, here is the list of the top JavaScript frameworks for front-end developers.</p>
<h2 id="heading-the-big-5-javascript-frameworks">The Big 5 JavaScript Frameworks</h2>
<p>The five JavaScript frameworks that currently dominate the market in terms of popularity and usage are:</p>
<ul>
<li>React </li>
<li>Vue </li>
<li>Angular </li>
<li>Ember</li>
<li>Backbone.js. </li>
</ul>
<p>They each have large communities. If you are a front-end developer or are going to start your new project on front-end technologies, these five are your best bets. Here’s a look at the npm trends over the last six months.</p>
<p><img src="https://lh3.googleusercontent.com/XxQMWDLC6oyQMOna5NKP_lDYYgmXgHnLclulqOZ-0C-l5n-hFw-q5BLnbM7hRGEB8kl9w7GSUAzf6K1gexsZrcp9O7T7ju_ns94qNUR_2-12cR2_Rn30F3f9ul4iO2rGqdRv1SYl" alt="Image" width="1080" height="450" loading="lazy"></p>
<p><img src="https://lh3.googleusercontent.com/cSAcJvog37qO1rB1OCFvKPouN6R5OcbHam-Qmzc6Ei-nnOLxr-FoeeHD6sKQKEd-b3vmushcuEFjN02EPKbzYkEuOQlHtJizRRS2zVD77TUKRM-leOcGJpa1ZZqzQUAaD3EdUvRM" alt="Image" width="1098" height="332" loading="lazy"></p>
<h2 id="heading-1-react">1. React</h2>
<p>React is the definite leader in the JS world. This JavaScript framework uses a <a target="_blank" href="https://en.wikipedia.org/wiki/Reactive_programming">reactive approach</a> and also introduces many of its own concepts for front-end web development. </p>
<p>To use React , you’ll have to learn to use a plethora of additional tools to reach high flexibility in front-end development. For example, here's a less exhaustive list of libraries you can use with React: Redux, MobX, Fluxy, Fluxible, or RefluxJS. React can also be used with jQuery AJAX, fetch API, Superagent, and Axios.</p>
<h3 id="heading-concurrent-mode">Concurrent Mode</h3>
<div class="embed-wrapper">
        <blockquote class="twitter-tweet">
          <a href="https://twitter.com/reactjs/status/1187411505001746432"></a>
        </blockquote>
        <script defer="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></div>
<p>React is constantly working towards improving concurrent mode. To take this forward, React Conf 2019 wrapped up last month where the React team talked about improving <a target="_blank" href="https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html">Concurrent Mode and the Suspense model</a>. Both the features make React apps more responsive by rendering trees without blocking threads. This allows React to focus on high priority tasks like responding to user input.</p>
<h3 id="heading-suspense">Suspense</h3>
<p>React also introduced Suspense to improve the developer’s experience when handling asynchronous data fetching in React apps. In short, the new update to Suspense lets the component wait until a condition is met. </p>
<p>Hooks are another important update to React 16.8. <a target="_blank" href="https://reactjs.org/docs/hooks-overview.html">React hooks</a> lets you use every important feature of React – server-side rendering, accessibility, concurrent mode, and suspense – all without writing a class.</p>
<p>React applications are divided into multiple components that contain both business logic and HTML markup functions. To improve the communication between components, developers can use either Flux or a similar JavaScript library. </p>
<p>React also introduced objects, like state and props. With the state and props objects, you can simply pass data from a component to the layout or from a parent component to a child component.</p>
<p><strong>Introduction to the React ecosystem:</strong></p>
<ul>
<li>The React library plus React router for implementing routes.</li>
<li><a target="_blank" href="https://reactjs.org/docs/react-dom.html">React-DOM</a> for DOM manipulation.</li>
<li>React developer tools for Firefox and Chrome browsers.</li>
<li><a target="_blank" href="https://reactjs.org/docs/introducing-jsx.html">React JSX</a>, a markup language that mixes HTML into JavaScript.</li>
<li>React Create App command line interface to set up a React project.</li>
<li>Redux and Axios libraries to organize communication with the backend team.</li>
</ul>
<p>No doubt, React is one of the most popular JavaScript frameworks. And, I think that React can be your first choice for creating advanced-grade apps. </p>
<h2 id="heading-2-angular-2-to-angular-9">2. Angular 2 to Angular 9</h2>
<p>Angular 9 will mark a turning point revealed by the Angular team at the recent AngularConnect 2019. According to the update, the team is planning to make the <a target="_blank" href="https://angular.io/guide/ivy">Angular Ivy compiler</a> available for all apps. The main benefit of Angular Ivy is that it is able to reduce the size of applications. </p>
<p>Angular today has become very advanced and modular to use for front-end development. Previously you could insert a link to the AngularJS library in the main HTML file, but now you can do the same by installing separate modules. </p>
<p>Angular's flexibility is commendable. That’s why Angular's 1.x versions are still in demand. However, many developers currently rely on Angular 2+ because of its MVC architecture which has changed substantially to a component based architecture.  </p>
<p>Angular has a couple of additional challenges. You're almost obliged to use TypeScript to ensure type safety in Angular apps. TypeScript makes the Angular 2+ framework not so pleasant to work with. </p>
<p><strong>Angular’s ecosystem is comprised of:</strong></p>
<ul>
<li>For quick project setup, Angular's command line interface is helpful.</li>
<li>Developers will get a set of modules for Angular projects: @angular/common, @angular/compiler, @angular/core, @angular/forms, @angular/http, @angular/platform-browser, @angular/platform-browser-dynamic, @angular/router, and @angular/upgrade. </li>
<li>Angular uses Zone.js a JavaScript library to implement zones in Angular apps.</li>
<li>TypeScript and CoffeeScript both can be used with Angular.</li>
<li>For communication with server-side apps, Angular uses RxJS and the Observable pattern.</li>
<li>Angular Augury for <em>debugging</em> Angular apps.</li>
<li>Angular Universal for creating server-side apps with Angular.</li>
</ul>
<p>Angular2 is a complete JavaScript framework with all the tools a modern front-end developer needs. You can choose Angular if you don’t like to work with additional libraries as with React.</p>
<h2 id="heading-3-vue">3. Vue</h2>
<p>The Snyk JavaScript framework report for 2019 is out. The report mainly focused on security risks in both React and Angular.</p>
<div class="embed-wrapper">
        <blockquote class="twitter-tweet">
          <a href="https://twitter.com/snyksec/status/1189527376197246977"></a>
        </blockquote>
        <script defer="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></div>
<p>The concept of Vue has been taken from Angular and React, but Vue is better in many ways. I’ll talk about its features, but first check out what the <a target="_blank" href="https://snyk.io/blog/javascript-frameworks-security-report-2019/">Synk report</a> says about Vue's front-end security. Vue has been downloaded 40 million times this year and records only <a target="_blank" href="https://snyk.io/vuln/npm:vue">four direct vulnerabilities</a>. All of them have been fixed. </p>
<p>For any front-end developer unfamiliar with Vue, let’s clarify several points. </p>
<p>With Vue you store component logic and layouts along with stylesheets in one file. This is the same way React works, without stylesheets. To let components talk to each other, Vue uses the props and state objects. This approach also existed in React before Vue adopted it.</p>
<p>Similar to Angular, Vue wants you to mix HTML layouts with JavaScript. You have to use Vue directives such as v-bind or v-if to interpolate values from the component logic to templates.</p>
<p>One of the reasons why Vue is worth considering instead of React is because of the Redux library that’s often used in large-scale React applications. As explained in the React section, when a React+Redux app grows bigger, you’ll spend a lot of time applying small changes to multiple files instead of actually working on features. The Vuex library – a Flux-like state management tool designed for Vue – seems less unwieldy than Redux.</p>
<p>If you're choosing between Vue and Angular, the reasons to opt for Vue over Angular can be reduced to the following: Angular is an over-complicated, full-fledged framework with a restrictive nature; Vue is much simpler and less restrictive than Angular.</p>
<p>Another advantage of Vue over Angular and React is that you don’t have to learn JavaScript once more. </p>
<p><strong>An introduction to the VueJS ecosystem:</strong></p>
<ul>
<li>Vuex comes with a dedicated library for application management.</li>
<li>Vuex is similar to the concept of Flux.</li>
<li>You will get Vue-loader for components and vue.js devtools for Chrome and Firefox browsers.</li>
<li>Vue-resource and Axios tools for communication between Vue and the backend source.</li>
<li>Vue.js support Nuxt.js for creating server-side applications with Vue; Nuxt.js is basically a competitor to Angular Universal.</li>
<li>You will get a Weex JavaScript library with Vue syntax that is used for mobile app development.</li>
</ul>
<p>Vue is excellent in terms of its workflow to other frameworks. I might opt for Vue because it’s less complicated than React and Angular JS and a great choice for developing enterprise-level apps.</p>
<h2 id="heading-4-ember">4. Ember</h2>
<p>Ember 3.13 released this year with some new updates and features. Ember is just like Backbone and AngularJS, and is also one of the oldest JavaScript frameworks. But with the new update, <a target="_blank" href="https://blog.emberjs.com/2019/09/25/ember-3-13-released.html">Ember 3.13</a> is compatible with new bug fixes, performance improvements, and deprecation. Tracked property updates have also been introduced that allow simpler ways of tracking state change in the ergonomic system of Ember apps.</p>
<p>Ember has a relatively intricate architecture, which will allow you to quickly build huge client-side applications. It realizes a typical MVC JavaScript framework, and Ember’s architecture comprises the following parts: adapters, components, controllers, helpers, models, routes, services, templates, utils, and addons.</p>
<p>One of Ember’s best features is its command line interface tool. The Ember CLI helps front-end developers be highly productive and lets them complete projects on time. You can not only create new projects with ready setups, but you can also create controllers, components, and project files using automatic generation. </p>
<p><strong>The EmberJS ecosystem is comprised of:</strong></p>
<ul>
<li>Ember CLI tool for quick prototyping and managing dependencies.</li>
<li>Ember server built into the framework for the development of apps.</li>
<li>You'll get Ember.js library and Ember Data for data management.</li>
<li>Handlebars template engine for Ember applications.</li>
<li>QUnit testing framework for Ember.</li>
<li>Ember Inspector development tool for Chrome and Firefox browsers.</li>
<li>Ember Observer for public storage and Ember addons to implement generic functionalities.</li>
</ul>
<p>Although Ember is underrated, it's perfect for creating complex client-side apps. </p>
<h2 id="heading-5-backbonejs">5. Backbone.js</h2>
<p>Backbone is a JavaScript framework based on the MVC architecture. In Backbone.js, the View of MVC helps implement component logic similarly to a Controller. Backbone view can use engines like Mustache and Underscore.js.</p>
<p>Backbone is an easy to use JavaScript framework that allows for quick development of single page applications. To use Backbone.js to the fullest extent, you’ll have to choose tools: Chaplin, Marionette, Thorax, Handlebars or Mustache, and so on. </p>
<p>If you need to design an app that has different types of users, Backbone collections (arrays) can be used here to separate the models. Backbone.Events can be used with Backbone models, collections, routes, and views. </p>
<p><strong>Introducing the BackboneJS ecosystem:</strong></p>
<ul>
<li>The Backbone library consists of events, models, collections, views, and router.</li>
<li>Underscore.js, a JavaScript library with helper functions that you can use to write cross-browser JavaScript.</li>
<li>You can use template engines such as Mustache and jQuery-tmpl.</li>
<li><a target="_blank" href="http://backplug.io/">BackPlug</a> online repository with a lot of ready solutions for Backbone-based apps.</li>
<li>Backbone generator CLI for building Backbone apps.</li>
<li>Marionette, Thorax, and Chaplin JavaScript libraries to develop an advanced architecture for Backbone apps.</li>
</ul>
<p>Backbone.js is a perfect choice for front-end and back-end development as it supports REST APIs that are used to synchronize the front-end and back-end. </p>
<h2 id="heading-need-more-help">Need More Help?</h2>
<p>All front-end developers out there, if you need help with JavaScript frameworks, feel free to <a target="_blank" href="https://www.valuecoders.com/contact">get in touch</a>. Or, you can also contact us to <a target="_blank" href="https://www.valuecoders.com/hire-developers/hire-reactjs-developers">hire ReactJS developers</a>, Vue developers, or Angular developers. </p>
<blockquote>
<p>_Or, leave me a note or <a target="_blank" href="https://twitter.com/ValueCoders?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor">Tweet</a> out to me._</p>
</blockquote>
<p>Remember this article gives you a general roadmap on JavaScript frameworks. Tell me if I have missed something, and we can discuss that. I hope it will also help achieve your front-end development goals.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to build a SPA using Vue.js, Vuex, Vuetify, and Firebase: adding authentication with Firebase ]]>
                </title>
                <description>
                    <![CDATA[ By Jennifer Bland Part 4: learn how to use Firebase to add authentication and a cart Meal Prep application Learn how to create a meal delivery website using Vue.js, Vuex, Vue Router, and Firebase. This is part four of my four-part series on building... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-spa-using-vue-js-vuex-vuetify-and-firebase-adding-authentication-with-firebase-d9932d1e4365/</link>
                <guid isPermaLink="false">66d460d8a326133d12440a6e</guid>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ vue ]]>
                    </category>
                
                    <category>
                        <![CDATA[ #vue-router ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Vue.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Vuex ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 28 Nov 2018 01:13:39 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*_oxBC3QDl02cB2MDOzGXZg.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jennifer Bland</p>
<h4 id="heading-part-4-learn-how-to-use-firebase-to-add-authentication-and-a-cart">Part 4: learn how to use Firebase to add authentication and a cart</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/OEAiRGPTXUXg4SP-gqbkQthWuYTwQrThqkdu" alt="Image" width="800" height="411" loading="lazy">
<em>Meal Prep application</em></p>
<p>Learn how to create a meal delivery website using Vue.js, Vuex, Vue Router, and Firebase.</p>
<p>This is part four of my four-part series on building a Vue application. Here is a list of all the parts:</p>
<p><a target="_blank" href="https://medium.com/p/838b40721a07">Part 1: Installing Vue and Building an SPA using Vuetify and Vue Router</a></p>
<p><a target="_blank" href="https://medium.com/p/fc5bd065fe18">Part 2: Using Vue Router</a></p>
<p><a target="_blank" href="https://medium.com/p/f8036aa464ad">Part 3: Using Vuex and accessing API</a></p>
<p><a target="_blank" href="https://medium.com/p/d9932d1e4365">Part 4: Using Firebase for Authentication &amp; Cart</a></p>
<h3 id="heading-recap">Recap</h3>
<p>In the first part of this series, we created our Vue application using the Vue CLI. Also, we added Vuetify to the app. We used Vuetify to style our home page.</p>
<p>In the second part, we used Vue Router to add navigation between the different pages of our app. We added components for all the pages in our application.</p>
<p>In the third part, we were introduced to Vuex. We signed up for an API to provide recipes and used axios to retrieve them. This data was stored in the Vuex store which made it accessible to every component in the application.</p>
<h3 id="heading-what-is-firebase">What is Firebase?</h3>
<p>Firebase is a real-time cloud infrastructure for client-side apps. Firebase can turn any <em>Frontend</em> application into a full-stack product capable of scaling infinitely in the cloud. It abstracts away most of your complex server-side features like user authentication, data persistence, file storage, and microservices, so you can focus on building an awesome experience for the end user.</p>
<p>The first step is to go to <a target="_blank" href="https://firebase.google.com">firebase and create a new account</a>. Log in to the account that you created. You will see this dashboard:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/nh3agjDtQIfZb5NsgLroWojeEEZ0Nm-uI614" alt="Image" width="800" height="649" loading="lazy">
<em>Firebase Demo</em></p>
<p>Click the <code>Add Project</code> button. Enter a name for your project. I entered “meal-prep” for the name of my project. Check all checkboxes. Then click the <code>create project</code> button.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/33vedZNLJ3WoqpIr7XzQRpXznXO8TOfQHY-Z" alt="Image" width="587" height="706" loading="lazy">
<em>Add new project dialog on Firebase</em></p>
<p>Once your project is created, Firebase will take you to your project’s home page.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/G80ee1kcRa8BJmt-ZjJp7yvrZEzpiply5seN" alt="Image" width="800" height="347" loading="lazy">
<em>Project Home Page</em></p>
<p>We need to integrate our project’s configuration into our meal-prep application. Click on the web button to add Firebase to your application. (NOTE: if you are not sure which button that is, it is the button with the <code>&lt;</code>;/&gt;. In the image above, the button is right above the words “get started.” Click the copy button to copy the snippet to your clipboard.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/nstMKziQenAP2sNjXnSyoPGKRNuVdEjTufzq" alt="Image" width="800" height="546" loading="lazy">
<em>Firebase config snippet</em></p>
<p>Next, we need to incorporate this snippet into our meal prep application. You can initialize your firebase application in the <code>main.js</code> file. You can do it in the <code>App.vue</code> file.</p>
<p>Instead, we are going to create a new directory called firebase in the src folder. Inside this new directory create a file called <code>index.js</code>. Paste the contents of your clipboard into this file. Remove the two lines with the <code>script</code> tags. In the first line of the file import firebase. On the last line initialize firebase. Your file should look like this:</p>
<pre><code><span class="hljs-keyword">import</span> firebase <span class="hljs-keyword">from</span> <span class="hljs-string">'firebase'</span>;<span class="hljs-keyword">const</span> config = {    <span class="hljs-attr">apiKey</span>: <span class="hljs-string">"&lt;youKeyHere&gt;"</span>,    <span class="hljs-attr">authDomain</span>: <span class="hljs-string">"&lt;youKeyHere&gt;"</span>,    <span class="hljs-attr">databaseURL</span>: <span class="hljs-string">"&lt;youKeyHere&gt;"</span>,    <span class="hljs-attr">projectId</span>: <span class="hljs-string">"&lt;youKeyHere&gt;"</span>,    <span class="hljs-attr">storageBucket</span>: <span class="hljs-string">"&lt;youKeyHere&gt;"</span>,    <span class="hljs-attr">messagingSenderId</span>: <span class="hljs-string">"&lt;youKeyHere&gt;"</span>};firebase.initializeApp(config);
</code></pre><p>We are importing firebase from an npm package that we have not installed yet. Let’s install it now. In your terminal, install firebase with this command:</p>
<pre><code>npm install firebase --save
</code></pre><p>Now that we have installed firebase and created a config file, we need to add this file to our application so Vue is aware of it. Open up the <code>main.js</code> file and import in the config file we created. Here is what my <code>main.js</code> file looks like:</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-string">'@babel/polyfill'</span>;<span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;<span class="hljs-keyword">import</span> <span class="hljs-string">'./plugins/vuetify'</span>;<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App.vue'</span>;<span class="hljs-keyword">import</span> router <span class="hljs-keyword">from</span> <span class="hljs-string">'./router'</span>;<span class="hljs-keyword">import</span> store <span class="hljs-keyword">from</span> <span class="hljs-string">'./store'</span>;<span class="hljs-keyword">import</span> <span class="hljs-string">'@/firebase/'</span>;Vue.config.productionTip = <span class="hljs-literal">false</span>;<span class="hljs-keyword">new</span> Vue({    router,    store,    <span class="hljs-attr">render</span>: <span class="hljs-function"><span class="hljs-params">h</span> =&gt;</span> h(App)}).$mount(<span class="hljs-string">'#app'</span>);
</code></pre><p>Go back to your firebase console in the browser. Click on <code>Authentication</code>. Click on the <code>set up sign-in method</code> button.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/eKoTHvMZxWj28bIBc1vy18y4Q4fnSSypzEjD" alt="Image" width="800" height="368" loading="lazy">
<em>Setting up authentication in firebase</em></p>
<p>In the list of sign-in providers, click on Email/Password:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/yiS92UoxyI60pQDvGKkmeduz0cqML4qRBPuw" alt="Image" width="800" height="397" loading="lazy">
<em>List of sign-in providers</em></p>
<p>Enable the option to all users to sign up using their email address and password. Then click the <code>save</code> button.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/85suaEwdDT71E0k3QbSPegLPeABexqZGJ3ov" alt="Image" width="800" height="259" loading="lazy">
<em>Enable sign up using email and password</em></p>
<h4 id="heading-creating-sign-up-form">Creating Sign Up Form</h4>
<p>In a previous post, we stubbed out the Join.vue and Signin.vue files. These two files will have almost the same code. We will create the Join form first. When we are finished we will copy/paste it into the Signin form.</p>
<p>Open the Join.vue component. You can remove everything that is in the template. Vuetify has a default layout structure for components. It flows like this:</p>
<ul>
<li>v-container</li>
<li>v-layout</li>
<li>v-flex</li>
</ul>
<p>So let’s create that layout now in the component. The start of our file looks like this:</p>
<pre><code>&lt;template&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-container</span> <span class="hljs-attr">fill-height</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">v-layout</span> <span class="hljs-attr">align-center</span> <span class="hljs-attr">justify-center</span>&gt;</span>            <span class="hljs-symbol">&amp;lt;</span>v-flex xs12 sm8 md4&gt;            <span class="hljs-tag">&lt;/<span class="hljs-name">v-flex</span>&gt;</span>        <span class="hljs-tag">&lt;/<span class="hljs-name">v-layout</span>&gt;</span></span>    &lt;<span class="hljs-regexp">/v-container&gt;&lt;/</span>template&gt;
</code></pre><p>For the <code>v-container</code> we are adding <code>fill-height</code>. We add this so that it centers the form vertically in the window. For the <code>v-flex</code> we add <code>xs12</code> <code>sm8</code> and <code>md4</code> values. This is similar to Bootstrap’s column width definition. On extra-small devices, the form will take up all 12 columns meaning the whole screen. On small devices, the form will be 3/4 of the screen wide. On medium and large screens the form will be 1/3 of the screen.</p>
<p>Inside the <code>v-flex</code> we are going to use a <code>v-card</code>. We add <code>class=”elevation-12"</code> to the <code>v-card</code> so that it appears to be floating above the page. For the top of the form, we will use a <code>v-toolbar</code>. We give it a color of <code>primary</code>. For the default installation of Vuetify the primary color is blue. We want the text in the toolbar to be white text instead of the default black. To turn the text white we add <code>dark</code> to the <code>v-toolbar</code>.</p>
<p>Next, we have a <code>v-card-text</code>. Inside of it, we have a <code>v-form</code>. For the form we are giving it a reference with the name of <code>form</code>. We are assigning it to the <code>v-model</code> with a value of <code>valid</code>.</p>
<p>The last thing we add is <code>lazy-validation</code>. Our form needs to capture the user’s email and password. We will use two <code>v-text-field</code> to capture these values. To make things look better I have prepended an icon for each field. Each field has a <code>v-model</code> and <code>rules</code>.</p>
<p>Before the form is submitted the field will be validated against all rules that are defined. If they pass then you can submit the form. We will take advantage of this when the user clicks the Join button.</p>
<p>The last item to add to the form is a button. We add a <code>v-card-actions</code> and add a button. Here is what the template looks like for our component:</p>
<pre><code>&lt;template&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-container</span> <span class="hljs-attr">fill-height</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">v-layout</span> <span class="hljs-attr">align-center</span> <span class="hljs-attr">justify-center</span>&gt;</span>            <span class="hljs-symbol">&amp;lt;</span>v-flex xs12 sm8 md4&gt;                <span class="hljs-tag">&lt;<span class="hljs-name">v-card</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"elevation-12"</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-toolbar</span> <span class="hljs-attr">dark</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"primary"</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-toolbar-title</span>&gt;</span>Join Form<span class="hljs-tag">&lt;/<span class="hljs-name">v-toolbar-title</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-toolbar</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">;v-card-text</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-form</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"form"</span> <span class="hljs-attr">v-model</span>=<span class="hljs-string">"valid"</span> <span class="hljs-attr">lazy-validation</span>&gt;</span>;                            <span class="hljs-symbol">&amp;lt;</span>v-text-field prepend-icon="person" name="email" label="Email" type="email"                                          v-model="email" :rules="emailRules" required&gt;                            <span class="hljs-tag">&lt;/<span class="hljs-name">v-text-field</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">v-text-field</span> <span class="hljs-attr">prepend-icon</span>=<span class="hljs-string">"lock"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">label</span>=<span class="hljs-string">"Password"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"password"</span>                                          <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">required</span> <span class="hljs-attr">v-model</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">:rules</span>=<span class="hljs-string">"passwordRules"</span>&gt;</span>                            <span class="hljs-tag">&lt;/<span class="hljs-name">v-text-field</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">v-form</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-card-text</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-card-actions</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-spacer</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">v-spacer</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-btn</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"primary"</span> <span class="hljs-attr">:disabled</span>=<span class="hljs-string">"!valid"</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"submit"</span>&gt;</span>Join<span class="hljs-tag">&lt;/<span class="hljs-name">v-btn</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-card-actions</span>&gt;</span>                <span class="hljs-tag">&lt;/<span class="hljs-name">v-card</span>&gt;</span></span>            &lt;<span class="hljs-regexp">/v-flex&gt;        &lt;/</span>v-layout&gt;    &lt;<span class="hljs-regexp">/v-container&gt;&lt;/</span>template&gt;
</code></pre><p>We defined several models in our template. We need to add them to the <code>data</code> section of our script. In the script add a data object. We will add valid, email, password, emailRules and passwordRules.</p>
<p>Email and password will contain the values the user inputs into the two text fields. Valid will tell if our form has passed all the rules we have created. For email, we check to make sure that the field is not empty. We also check that the contents match a basic RegExp to validate the email address. For password, we check to make sure the field is not empty. We also check to make sure the password is at least six characters in length.</p>
<p>Here is what the data object looks like now:</p>
<pre><code>data() {    <span class="hljs-keyword">return</span> {        <span class="hljs-attr">valid</span>: <span class="hljs-literal">false</span>,        <span class="hljs-attr">email</span>: <span class="hljs-string">''</span>,        <span class="hljs-attr">password</span>: <span class="hljs-string">''</span>,        <span class="hljs-attr">emailRules</span>: [            <span class="hljs-function"><span class="hljs-params">v</span> =&gt;</span> !!v || <span class="hljs-string">'E-mail is required'</span>,            <span class="hljs-function"><span class="hljs-params">v</span> =&gt;</span> <span class="hljs-regexp">/.+@.+/</span>.test(v) || <span class="hljs-string">'E-mail must be valid'</span>        ],        <span class="hljs-attr">passwordRules</span>: [            <span class="hljs-function"><span class="hljs-params">v</span> =&gt;</span> !!v || <span class="hljs-string">'Password is required'</span>,            <span class="hljs-function"><span class="hljs-params">v</span> =&gt;</span>                v.length &gt;= <span class="hljs-number">6</span> ||                <span class="hljs-string">'Password must be greater than 6 characters'</span>        ]    };},
</code></pre><p>The last thing we need to add is methods. In methods, we have <code>submit()</code>. This method will validate our form first. If it passes validation then it will call an action in our Vuex store called <code>userJoin</code>. We pass it the email and password the user entered in the form.</p>
<p>Here is what the methods look like:</p>
<pre><code>methods: {    submit() {        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.$refs.form.validate()) {            <span class="hljs-built_in">this</span>.$store.dispatch(<span class="hljs-string">'userJoin'</span>, {                <span class="hljs-attr">email</span>: <span class="hljs-built_in">this</span>.email,                <span class="hljs-attr">password</span>: <span class="hljs-built_in">this</span>.password            });        }    }}
</code></pre><h4 id="heading-creating-userjoin-action-in-vuex">Creating userJoin Action in Vuex</h4>
<p>Open up the <code>store.js</code> file. We will create a new action called <code>userJoin</code>. By default the first parameter passed to this action is <code>context</code>. I will use object destructuring to get just <code>commit</code> from <code>context</code>. Commit is how I will call my mutation.</p>
<p>I will be using firebase to create the new user in the firebase database. To be able to use firebase in the store, I will need to import it. At the top of the file import firebase with this command:</p>
<pre><code><span class="hljs-keyword">import</span> firebase <span class="hljs-keyword">from</span> <span class="hljs-string">'firebase'</span>;
</code></pre><p>Firebase authentication provides a method called <code>createUserWithEmailAndPassword</code>. We will pass the user’s email and password into this method. If it succeeds in registering the user it will return a user object. When it succeeds we will call two mutations: <code>setUser</code> and <code>setIsAuthenticated</code>. Here is what the action looks like:</p>
<pre><code>userJoin({ commit }, { email, password }) {    firebase        .auth()        .createUserWithEmailAndPassword(email, password)        .then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {            commit(<span class="hljs-string">'setUser'</span>, user);            commit(<span class="hljs-string">'setIsAuthenticated'</span>, <span class="hljs-literal">true</span>);        })        .catch(<span class="hljs-function">() =&gt;</span> {            commit(<span class="hljs-string">'setUser'</span>, <span class="hljs-literal">null</span>);            commit(<span class="hljs-string">'setIsAuthenticated'</span>, <span class="hljs-literal">false</span>);        });}
</code></pre><p>This action calls two mutations. So let’s create then now. In mutations add a new mutation called <code>setUser</code>. Set the state value of user to the payload. Next, create a second mutation called <code>setIsAuthenticated</code>. Set the state value of isAuthenticated to the payload. Here is what the two mutations look like:</p>
<pre><code>setUser(state, payload) {    state.user = payload;},setIsAuthenticated(state, payload) {    state.isAuthenticated = payload;}
</code></pre><p>In state, we need to add two new value: <code>user</code> and <code>isAuthenticated</code>. Here is what state looks like now:</p>
<pre><code>state: {    <span class="hljs-attr">recipes</span>: [],    <span class="hljs-attr">apiUrl</span>: <span class="hljs-string">'https://api.edamam.com/search'</span>,    <span class="hljs-attr">user</span>: <span class="hljs-literal">null</span>,    <span class="hljs-attr">isAuthenticated</span>: <span class="hljs-literal">false</span>},
</code></pre><h4 id="heading-test-adding-a-new-user">Test Adding a New User</h4>
<p>Start your server with the command <code>npm run serve</code>. Click on the <code>Join</code> button in the navigation. Enter your email and a password and click the join button. When you click the button nothing visible happens. To verify that the user was registered, go the firebase console in your browser. Click on <code>Authentication</code>. You should see a list of users that have been registered for your application. Here you can see that the user I just registered was created.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/vYkETdpPAbqno517wwsXH-g6tHJWZQXcQnrj" alt="Image" width="800" height="162" loading="lazy">
<em>User has been registered</em></p>
<p>We need to notify the user that they have been successfully created. We will do this but later. First, we are going to copy and paste the contents of the Join.vue component into the <code>Signin.vue</code> component. There are only two changes you will need to make in the template. Change the title to “Login Form.” For the button make the text say “Login.” In the submit method have it dispatch to <code>userLogin</code>. Just to make sure you have it correct, here is what my entire Signin.vue file looks like:</p>
<pre><code>&lt;template&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-container</span> <span class="hljs-attr">fill-height</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">v-layout</span> <span class="hljs-attr">align-center</span> <span class="hljs-attr">justify-center</span>&gt;</span>            <span class="hljs-symbol">&amp;lt;</span>v-flex xs12 sm8 md4&gt;                <span class="hljs-tag">&lt;<span class="hljs-name">v-card</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"elevation-12"</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-toolbar</span> <span class="hljs-attr">dark</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"primary"</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-toolbar-title</span>&gt;</span>Login Form<span class="hljs-tag">&lt;/<span class="hljs-name">v-toolbar-title</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-toolbar</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">;v-card-text</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-form</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"form"</span> <span class="hljs-attr">v-model</span>=<span class="hljs-string">"valid"</span> <span class="hljs-attr">lazy-validation</span>&gt;</span>;                            <span class="hljs-symbol">&amp;lt;</span>v-text-field prepend-icon="person" name="email" label="Email" type="email"                                          v-model="email" :rules="emailRules" required&gt;                            <span class="hljs-tag">&lt;/<span class="hljs-name">v-text-field</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">v-text-field</span> <span class="hljs-attr">prepend-icon</span>=<span class="hljs-string">"lock"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">label</span>=<span class="hljs-string">"Password"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"password"</span>                                          <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">required</span> <span class="hljs-attr">v-model</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">:rules</span>=<span class="hljs-string">"passwordRules"</span>&gt;</span>                            <span class="hljs-tag">&lt;/<span class="hljs-name">v-text-field</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">v-form</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-card-text</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-card-actions</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-spacer</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">v-spacer</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-btn</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"primary"</span> <span class="hljs-attr">:disabled</span>=<span class="hljs-string">"!valid"</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"submit"</span>&gt;</span>Login<span class="hljs-tag">&lt;/<span class="hljs-name">v-btn</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-card-actions</span>&gt;</span>                <span class="hljs-tag">&lt;/<span class="hljs-name">v-card&amp;gt;</span>            &lt;/<span class="hljs-attr">v-flex</span>&amp;<span class="hljs-attr">gt</span>;        &lt;/<span class="hljs-attr">v-layout</span>&gt;</span></span>    &lt;<span class="hljs-regexp">/v-container&gt;&lt;/</span>template&gt;<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {    <span class="hljs-attr">name</span>: <span class="hljs-string">'Signin'</span>,    data() {        <span class="hljs-keyword">return</span> {            <span class="hljs-attr">valid</span>: <span class="hljs-literal">false</span>,            <span class="hljs-attr">email</span>: <span class="hljs-string">''</span>,            <span class="hljs-attr">password</span>: <span class="hljs-string">''</span>,            <span class="hljs-attr">emailRules</span>: [                <span class="hljs-function"><span class="hljs-params">v</span> =&gt;</span> !!v || <span class="hljs-string">'E-mail is required'</span>,                <span class="hljs-function"><span class="hljs-params">v</span> =&gt;</span> <span class="hljs-regexp">/.+@.+/</span>.test(v) || <span class="hljs-string">'E-mail must be valid'</span>            ],            <span class="hljs-attr">passwordRules</span>: [                <span class="hljs-function"><span class="hljs-params">v</span> =&gt;</span> !!v || <span class="hljs-string">'Password is required'</span>,                v =&amp;gt;                    v.length &gt;= <span class="hljs-number">6</span> ||                    <span class="hljs-string">'Password must be greater than 6 characters'</span>            ]        };    },    <span class="hljs-attr">methods</span>: {        submit() {            <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.$refs.form.validate()) {                <span class="hljs-built_in">this</span>.$store.dispatch(<span class="hljs-string">'userLogin'</span>, {                    <span class="hljs-attr">email</span>: <span class="hljs-built_in">this</span>.email,                    <span class="hljs-attr">password</span>: <span class="hljs-built_in">this</span>.password                });            }        }    }};</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">scoped</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>
</code></pre><p>That’s it. You have now created both the Join and Login forms.</p>
<p>We need to create the action for Login. Open up the <code>store.js</code> file. Create a new action called userLogin. We will use firebase to login the user. Firebase provides a method called <code>signInWithEmailAndPassword</code>. We will call this method and pass in the user’s email and password they entered into the form. If the user entered their email and password correctly then we will call the two mutations <code>setUser</code> and <code>setIsAuthenticated</code>. Here is what the <code>userLogin</code> action looks like:</p>
<pre><code>userLogin({ commit }, { email, password }) {    firebase        .auth()        .signInWithEmailAndPassword(email, password)        .then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {            commit(<span class="hljs-string">'setUser'</span>, user);            commit(<span class="hljs-string">'setIsAuthenticated'</span>, <span class="hljs-literal">true</span>);        })        .catch(<span class="hljs-function">() =&gt;</span> {            commit(<span class="hljs-string">'setUser'</span>, <span class="hljs-literal">null</span>);            commit(<span class="hljs-string">'setIsAuthenticated'</span>, <span class="hljs-literal">false</span>);        });},
</code></pre><h4 id="heading-redirecting-to-profile">Redirecting to Profile</h4>
<p>When a user successfully registers or login, we want to redirect them to their profile. When we created our app initially the Vue CLI 3 it created two routes for us. Those routes were <code>/</code> and <code>/about</code>. Eventually, the profile will contain a list of all recipes that the user has ordered from the <code>menu</code> page. Remember the button we put at the bottom of every recipe? That button will add the recipe to the user’s profile and store it in the database in firebase.</p>
<p>To redirect the user to the profile we will first import router at the top of the store.js file. The router is imported with the command:</p>
<pre><code><span class="hljs-keyword">import</span> router <span class="hljs-keyword">from</span> <span class="hljs-string">'@/router'</span>;
</code></pre><p>Next, in both actions we redirect the user to /about if they successfully register or login. You can do the redirection with this command:</p>
<pre><code>router.push(<span class="hljs-string">'/about'</span>);
</code></pre><p>If the user fails to register an account or login successfully we will redirect the user to the home page. <em>(NOTE: in a perfect scenario we will provide some notice to the user why the registration or login failed).</em> You can redirect them to the home page with this command:</p>
<pre><code>router.push(<span class="hljs-string">'/'</span>);
</code></pre><p>To test the redirection, start your server and click on the Login button. Enter the email and password you used when you created your user account. Click the Join button. If everything worked successfully you should be redirected to the About page.</p>
<h4 id="heading-updating-the-navigation">Updating the navigation</h4>
<p>The navigation has buttons for <code>Sign In</code> and <code>Join</code>. When a user successfully registers or login we would like to hide these two buttons. In their place, we want to show a <code>Logout</code> button.</p>
<p>Open up the <code>AppNavigation</code> component. We are going to group the two current buttons in a div. We are going to remove the class to hide the buttons on small and extra-small devices. Instead, we will place this class on the div. We add a <code>v-if</code> to the div to only show if the user is currently not authenticated. Below the <code>div</code> we will add a new button for Logout. This new button will have a style of outline with a color of white. When you click on this button it will call the method <code>logout</code>. We add a v-else to this button to show when the user is authenticated.</p>
<p>Next, add a method called <code>logout</code>. This method will call an action in our store called <code>userSignOut</code>.</p>
<p>We also need to add a new computed property called <code>isAuthenticated</code>. This property returns the value of isAuthenticated in the state of our store.</p>
<p>Here is what your AppNavigation should look like:</p>
<pre><code>&lt;template&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">v-navigation-drawer</span> <span class="hljs-attr">app</span> <span class="hljs-attr">v-model</span>=<span class="hljs-string">"drawer"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"brown lighten-2"</span> <span class="hljs-attr">dark</span> <span class="hljs-attr">disable-resize-watcher</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">v-list</span>&gt;</span>                <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"(item, index) in items"</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-list-tile</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">"index"</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-list-tile-content</span>&gt;</span>                            {{item.title}}                        <span class="hljs-tag">&lt;/<span class="hljs-name">v-list-tile-content</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">;</span>/<span class="hljs-attr">v-list-tile</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-divider</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">"`divider-${index}`"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">v-divider</span>&gt;</span>                <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>            <span class="hljs-tag">&lt;/<span class="hljs-name">v-list</span>&gt;</span>        <span class="hljs-tag">&lt;/<span class="hljs-name">v-navigation-drawer</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">v-toolbar</span> <span class="hljs-attr">app</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"brown darken-4"</span> <span class="hljs-attr">dark</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">v-toolbar-side-icon</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hidden-md-and-up"</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"drawer = !drawer"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">v-toolbar-side-icon</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">v-spacer</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hidden-md-and-up"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">v-spacer</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/"</span>&amp;<span class="hljs-attr">gt</span>;                &lt;<span class="hljs-attr">v-toolbar-title</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/"</span>&gt;</span>{{appTitle}}<span class="hljs-tag">&lt;/<span class="hljs-name">v-toolbar-title</span>&gt;</span>;            <span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">;v-btn</span> <span class="hljs-attr">flat</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hidden-sm-and-down"</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/menu"</span>&gt;</span>Menu<span class="hljs-tag">&lt;/<span class="hljs-name">v-btn</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">v-spacer</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hidden-sm-and-down"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">v-spacer</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">;div</span> <span class="hljs-attr">v-if</span>=<span class="hljs-string">"!isAuthenticated"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hidden-sm-and-down"</span>&gt;</span>                <span class="hljs-tag">&lt;<span class="hljs-name">v-btn</span> <span class="hljs-attr">flat</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/sign-in"</span>&gt;</span>SIGN IN<span class="hljs-tag">&lt;/<span class="hljs-name">v-btn</span>&gt;</span>                <span class="hljs-tag">&lt;<span class="hljs-name">v-btn</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"brown lighten-3"</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/join"</span>&gt;</span>JOIN<span class="hljs-tag">&lt;/<span class="hljs-name">v-btn</span>&gt;</span>            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-btn</span> <span class="hljs-attr">v-else</span> <span class="hljs-attr">outline</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"white"</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"logout"</span>&gt;</span>Logout<span class="hljs-tag">&lt;/<span class="hljs-name">v-btn</span>&gt;</span></span>        &lt;<span class="hljs-regexp">/v-toolbar&gt;    &lt;/</span>span&gt;&lt;<span class="hljs-regexp">/template&gt;&lt;script&gt;export default {    name: 'AppNavigation',    data() {        return {            appTitle: 'Meal Prep',            drawer: false,            items: [{ title: 'Menu' }, { title: 'Sign In' }, { title: 'Join' }]        };    },    computed: {        isAuthenticated() {            return this.$store.getters.isAuthenticated;        }    },    methods: {        logout() {            this.$store.dispatch('userSignOut');        }    }};&lt;/</span>script&gt;<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">scoped</span>&gt;</span><span class="css"><span class="hljs-selector-tag">a</span> {    <span class="hljs-attribute">color</span>: white;    <span class="hljs-attribute">text-decoration</span>: none;}</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>
</code></pre><p>We need to add the getter and action we just defined. Open up the <code>store.js</code> file. Create a new action called <code>userSignout</code>. This action will use firebase.auth() to sign the user out. After signing the user out, it sets the state variables <code>user</code> to null and <code>isAuthenticated</code> to false. Here is the <code>userSignout</code> method in the store:</p>
<pre><code>userSignOut({ commit }) {    firebase        .auth()        .signOut()        .then(<span class="hljs-function">() =&gt;</span> {            commit(<span class="hljs-string">'setUser'</span>, <span class="hljs-literal">null</span>);            commit(<span class="hljs-string">'setIsAuthenticated'</span>, <span class="hljs-literal">false</span>);            router.push(<span class="hljs-string">'/'</span>);        })        .catch(<span class="hljs-function">() =&gt;</span> {            commit(<span class="hljs-string">'setUser'</span>, <span class="hljs-literal">null</span>);            commit(<span class="hljs-string">'setIsAuthenticated'</span>, <span class="hljs-literal">false</span>);            router.push(<span class="hljs-string">'/'</span>);        });}
</code></pre><p>Next, we need to add a <code>getters</code> section to the store object. The <code>isAuthenticated</code> getters method will return true or false based on user authentication. Here is what the <code>getters</code> section of the store looks like:</p>
<pre><code>getters: {    isAuthenticated(state) {        <span class="hljs-keyword">return</span> state.user !== <span class="hljs-literal">null</span> &amp;&amp; state.user !== <span class="hljs-literal">undefined</span>;    }}
</code></pre><h3 id="heading-adding-recipes-to-database">Adding Recipes to Database</h3>
<p>Once a user is logged in they can click on any recipe to add it to their account. Their recipes will be shown in their profile which is the <code>/about</code> route. We need a database to store these recipes. Go to your firebase console in the browser. Click on <code>database</code> in the left side navigation panel. On the next screen you will see buttons to create a realtime database or a cloud firestore database. Make sure you create a new realtime database. In the dialog make sure you select to <code>start in test mode</code>. Then click the <code>enable</code> button.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/nHYgB0KpSgNkOE49AhvBos0IHr3mWw35ZJQJ" alt="Image" width="736" height="461" loading="lazy">
<em>Start database in test mode</em></p>
<p>Now we want to store the user’s recipes in the database. Open up the MealRecipes component. If a user tries to order a recipe and they are not logged in then we should redirect them to the login page. So let’s take care of that now. On the <code>Order</code> button add an @click that calls the method orderRecipe. Be sure to pass in <code>item</code> as an argument to the method. Your button should look like this:</p>
<pre><code>&lt;v-card-actions&gt;    &amp;lt;v-btn color=<span class="hljs-string">"green"</span> dark @click=<span class="hljs-string">"orderRecipe(item)"</span>&gt;Order&lt;<span class="hljs-regexp">/v-btn&gt;&lt;/</span>v-card-actions&gt;
</code></pre><p>Before we create our method, we will create a computed value for isAuthenticated. This is the exact same code we used in <code>AppNavigation</code> earlier to show and hide the login and logout button correctly. Add a computed isAuthenticated. It should look like this:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {    <span class="hljs-attr">name</span>: <span class="hljs-string">'MealRecipes'</span>,    <span class="hljs-attr">computed</span>: {        recipes() {            <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.$store.state.recipes;        },        isAuthenticated() {            <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.$store.getters.isAuthenticated;        }    }};
</code></pre><p>Now we are ready to create our orderRecipe method. Add this method and its parameter. In this method, we want to first check if the user is logged in or not. If they are not we want to redirect them to <code>/sign-in</code> . If they are signed in then we want to call an action in the Vuex store that will append the recipe to the user account in the database. Here is what our method looks like:</p>
<pre><code>methods: {    orderRecipe(item) {        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isAuthenticated) {            <span class="hljs-built_in">this</span>.$store.dispatch(<span class="hljs-string">'addRecipe'</span>, item);        } <span class="hljs-keyword">else</span> {            <span class="hljs-built_in">this</span>.$router.push(<span class="hljs-string">'/sign-in'</span>);        }    }}
</code></pre><p>Open up the store.js file. We need to create a new action to add recipes. In this action, we are going to use firebase to add the recipe to a database called <code>users</code>. When the user was registered in firebase they were assigned a unique userid. We will be using this <code>uid</code> to store the name of the recipe in the database.</p>
<p>In this action, we will be using <code>state</code> to get the value of the currently selected user. The <code>user</code> in <code>state</code> is an object. That object has a key called user. In that object, we will find the <code>uid</code>. We use that to push the title of the selected recipe into the database. Here is the action:</p>
<pre><code>addRecipe({ state }, payload) {    firebase        .database()        .ref(<span class="hljs-string">'users'</span>)        .child(state.user.user.uid)        .push(payload.recipe.label);}
</code></pre><p>Now start your server and log in. Select a diet from the menu page. Then order a couple of recipes. The recipes you ordered should be shown in the database in firebase.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/SBJUuIRCRWT2Fu3iAiZeEERyYXPTfeLaSLwt" alt="Image" width="800" height="273" loading="lazy">
<em>Recipes added to the database</em></p>
<p>Now that we have the recipes added to the database, we actually need to display them on the profile page for the user. Open up the <code>About.vue</code> file. Whenever this page is loaded it should fetch all the user’s recipes. To do this we add <code>mounted()</code> in our script. This will call a method called <code>getRecipes</code>.</p>
<p>Let’s create that method now. In the method, we are going to call an action in our Vuex store that will get all the user’s recipes. We have not created this action in the store yet but in simple terms, this action will get the user’s recipes. Then it will store them in a variable in <code>state</code> called <code>userRecipes</code>.</p>
<p>Before we leave About.vue, add a computed property for <code>userRecipes</code>. This will return the <code>userRecipes</code> from <code>state</code> in our store. This is what About.vue script should look like:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {    <span class="hljs-attr">name</span>: <span class="hljs-string">'About'</span>,    <span class="hljs-attr">computed</span>: {        userRecipes() {            <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.$store.state.userRecipes;        }    },    mounted() {        <span class="hljs-built_in">this</span>.getRecipes();    },    <span class="hljs-attr">methods</span>: {        getRecipes() {            <span class="hljs-built_in">this</span>.$store.dispatch(<span class="hljs-string">'getUserRecipes'</span>);        }    }};
</code></pre><p>Next, open up your <code>store.js</code> file. We need to create the <code>getUserRecipes</code> action. When the user logins we store a variable in <code>state</code> called user. This variable will have the unique user ID assigned to that user when it was registered in firebase. We want to get all the recipes in the users database that have this user ID. Once we get all the recipes we want to set userRecipes to contain them. Here is the getUserRecipes action:</p>
<pre><code>getUserRecipes({ state, commit }) {    <span class="hljs-keyword">return</span> firebase        .database()        .ref(<span class="hljs-string">'users/'</span> + state.user.user.uid)        .once(<span class="hljs-string">'value'</span>, <span class="hljs-function"><span class="hljs-params">snapshot</span> =&gt;</span> {            commit(<span class="hljs-string">'setUserRecipes'</span>, snapshot.val());        });}
</code></pre><p>In our mutations, we need to add a <code>setUserRecipes</code>. It looks like this:</p>
<pre><code>setUserRecipes(state, payload) {    state.userRecipes = payload;}
</code></pre><p>We also need to add a <code>userRecipes</code> in <code>state</code>. We set its initial value to an empty array. Here is my entire state object:</p>
<pre><code>state: {    <span class="hljs-attr">recipes</span>: [],    <span class="hljs-attr">apiUrl</span>: <span class="hljs-string">'https://api.edamam.com/search'</span>,    <span class="hljs-attr">user</span>: <span class="hljs-literal">null</span>,    <span class="hljs-attr">isAuthenticated</span>: <span class="hljs-literal">false</span>,    <span class="hljs-attr">userRecipes</span>: []},
</code></pre><p>Now that we are getting the recipes we need to display them on the page to the user. So go back to your <code>About.vue</code> file. In the template, we are going to loop through all the user’s recipes and display them. I am going to show you my code for the template first then explain what I have done:</p>
<pre><code>&lt;template&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-container</span> &gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">v-layout</span> <span class="hljs-attr">column</span>&gt;</span>;            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"title my-3"</span>&gt;</span>My Recipes<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"(item, idx) in userRecipes"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"subheading mb-2"</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">"idx"</span>&gt;</span>                {{item}}            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>        <span class="hljs-tag">&lt;/<span class="hljs-name">v-layout</span>&gt;</span>    <span class="hljs-tag">&lt;/<span class="hljs-name">v-container</span>&gt;</span></span>&lt;/template&gt;
</code></pre><p>I have set the layout to be <code>column</code>. I did this because I want each recipe to be listed on the page. To make things look clearer I have added a title. I added my-3 to add margin-top and margin-bottom so that there is spacing between the title and the list of recipes. Next, I looped through each recipe and display it. This is what the user sees if they have recipes:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/AXzGqeL9LhTRcYHIFkQgEjQwRAW4UFRP4Enr" alt="Image" width="800" height="113" loading="lazy">
<em>List of my recipes</em></p>
<p>This is great, but when if a user logs in and they do not have any recipes? They see the title “My Recipes” and a blank page. This is not a user-friendly design. So let’s change it to display something more friendly.</p>
<p>We will display a button that will take the user to the <code>menu</code> page. In our template, we will add this button. To make the button redirect to the menu page we can add <code>to=”/menu”</code> to the button. Here is my final template for the <code>About.vue</code> component.</p>
<pre><code>&lt;template&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-container</span> &gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">v-layout</span> <span class="hljs-attr">column</span>&gt;</span>;            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"title my-3"</span>&gt;</span>My Recipes<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"(item, idx) in userRecipes"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"subheading mb-2"</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">"idx"</span>&gt;</span>                {{item}}            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>            <span class="hljs-symbol">&amp;lt;</span>v-flex mt-4&gt;                <span class="hljs-tag">&lt;<span class="hljs-name">v-btn</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"primary"</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/menu"</span>&gt;</span>Go To Menu<span class="hljs-tag">&lt;/<span class="hljs-name">v-btn</span>&gt;</span>            <span class="hljs-tag">&lt;/<span class="hljs-name">v-flex</span>&gt;</span>        <span class="hljs-tag">&lt;/<span class="hljs-name">v-layout</span>&gt;</span></span>    &lt;<span class="hljs-regexp">/v-container&gt;&lt;/</span>template&gt;
</code></pre><h4 id="heading-showing-profile-in-navigation">Showing Profile in Navigation</h4>
<p>The last thing we need to add is the ability to show a link to the profile in the navigation. Just like the logout button, this should only be shown if the user is authenticated.</p>
<p>Open up the AppNavigation components. We are going to group the profile button and the logout button in a div. This is the same thing we did earlier for the <code>Sign In</code> and <code>Join</code> buttons. Add a div and move the logout button to be inside this div. Add another button for <code>profile</code>. This button will be flat just like the <code>Sign In</code> button.</p>
<p>Here is what my AppNavigation looks like now:</p>
<pre><code>&lt;template&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">v-navigation-drawer</span> <span class="hljs-attr">app</span> <span class="hljs-attr">v-model</span>=<span class="hljs-string">"drawer"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"brown lighten-2"</span> <span class="hljs-attr">dark</span> <span class="hljs-attr">disable-resize-watcher</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">v-list</span>&gt;</span>                <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"(item, index) in items"</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-list-tile</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">"index"</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-list-tile-content</span>&gt;</span>                            {{item.title}}                        <span class="hljs-tag">&lt;/<span class="hljs-name">v-list-tile-content</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">;</span>/<span class="hljs-attr">v-list-tile</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-divider</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">"`divider-${index}`"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">v-divider</span>&gt;</span>                <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>            <span class="hljs-tag">&lt;/<span class="hljs-name">v-list</span>&gt;</span>        <span class="hljs-tag">&lt;/<span class="hljs-name">v-navigation-drawer</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">v-toolbar</span> <span class="hljs-attr">app</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"brown darken-4"</span> <span class="hljs-attr">dark</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">v-toolbar-side-icon</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hidden-md-and-up"</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"drawer = !drawer"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">v-toolbar-side-icon</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">v-spacer</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hidden-md-and-up"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">v-spacer</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/"</span>&amp;<span class="hljs-attr">gt</span>;                &lt;<span class="hljs-attr">v-toolbar-title</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/"</span>&gt;</span>{{appTitle}}<span class="hljs-tag">&lt;/<span class="hljs-name">v-toolbar-title</span>&gt;</span>;            <span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">;v-btn</span> <span class="hljs-attr">flat</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hidden-sm-and-down"</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/menu"</span>&gt;</span>Menu<span class="hljs-tag">&lt;/<span class="hljs-name">v-btn</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">v-spacer</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hidden-sm-and-down"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">v-spacer</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">;div</span> <span class="hljs-attr">v-if</span>=<span class="hljs-string">"!isAuthenticated"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hidden-sm-and-down"</span>&amp;<span class="hljs-attr">gt</span>;                &lt;<span class="hljs-attr">v-btn</span> <span class="hljs-attr">flat</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/sign-in"</span>&gt;</span>SIGN IN<span class="hljs-tag">&lt;/<span class="hljs-name">v-btn</span>&gt;</span>                <span class="hljs-tag">&lt;<span class="hljs-name">v-btn</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"brown lighten-3"</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/join"</span>&gt;</span>JOIN<span class="hljs-tag">&lt;/<span class="hljs-name">v-btn</span>&gt;</span>            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">v-else</span>&gt;</span>                <span class="hljs-tag">&lt;<span class="hljs-name">v-btn</span> <span class="hljs-attr">flat</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/about"</span>&gt;</span>PROFILE<span class="hljs-tag">&lt;/<span class="hljs-name">v-btn</span>&gt;</span>                <span class="hljs-tag">&lt;<span class="hljs-name">v-btn</span> <span class="hljs-attr">outline</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"white"</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"logout"</span>&gt;</span>Logout<span class="hljs-tag">&lt;/<span class="hljs-name">v-btn</span>&gt;</span>            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>        &lt;<span class="hljs-regexp">/v-toolbar&gt;    &lt;/</span>span&gt;&lt;/template&gt;
</code></pre><h3 id="heading-adding-route-guards">Adding Route Guards</h3>
<p>Currently, the user can navigate to the profile page by typing it into the URL of the browser We don’t want to let users do this if they are not logged in. Vue Router provides the ability to add route guards before navigating to a URL. We want to test if a user is authenticated before allowing them to redirect to the <code>/about</code> page.</p>
<p>Open up the <code>router.js</code> file. Route guards work in conjunction with meta tags. Find the <code>/about</code> route. We will add a <code>authRequired</code> meta tag to it. The route should look like this:</p>
<pre><code>{    <span class="hljs-attr">path</span>: <span class="hljs-string">'/about'</span>,    <span class="hljs-attr">name</span>: <span class="hljs-string">'about'</span>,    <span class="hljs-attr">component</span>: () =&amp;gt; <span class="hljs-keyword">import</span>(<span class="hljs-string">'./views/About.vue'</span>),    <span class="hljs-attr">meta</span>: {        <span class="hljs-attr">authRequired</span>: <span class="hljs-literal">true</span>    }},
</code></pre><p>Route guards are checked in a method called beforeEach that is part of Vue Router. This method is passed three parameters:</p>
<ul>
<li>the route you are going to</li>
<li>the route you came from</li>
<li>a next method that continues with the current route</li>
</ul>
<p>Our beforeEach method will check every route that we are going to to see if it contains the meta tag of authRequired. If it does, it will check to see if the user is Authenticated. If the user is not authenticated it will redirect them to the <code>/sign-in</code> page. If the user is logged in then it will allow the route to proceed. If a user routes to any page that does not have the authRequired meta tag then the route will proceed.</p>
<p>Here is the method I have added to my router to do this checking:</p>
<pre><code>router.beforeEach(<span class="hljs-function">(<span class="hljs-params">to, <span class="hljs-keyword">from</span>, next</span>) =&gt;</span> {    <span class="hljs-keyword">if</span> (to.matched.some(<span class="hljs-function"><span class="hljs-params">record</span> =&gt;</span> record.meta.authRequired)) {        <span class="hljs-keyword">if</span> (!store.state.user) {            next({                <span class="hljs-attr">path</span>: <span class="hljs-string">'/sign-in'</span>            });        } <span class="hljs-keyword">else</span> {            next();        }    } <span class="hljs-keyword">else</span> {        next();    }});
</code></pre><h3 id="heading-get-the-code">Get the Code</h3>
<p>Even though this is a 4-part series, you can get the <a target="_blank" href="https://github.com/ratracegrad/meal-prep">finished code in my GitHub account.</a> Please help me out and <strong>star the repo</strong> when you get the code.</p>
<h3 id="heading-summary">Summary</h3>
<p>In this part of this series, you have learned:</p>
<ul>
<li>What is firebase</li>
<li>Using firebase to authenticate users who sign in with email and password</li>
<li>Using firebase to store the recipes a user has ordered</li>
<li>Using route guards to not users access pages if they are not authenticated</li>
<li>Display user’s list of recipes from the database on firebase</li>
</ul>
<p>If you enjoyed this article please clap for it. If you think somebody else would benefit from this article please share it with them.</p>
<p>If you have any questions or find anything wrong with the code, please leave a comment. If there are other topics you would like for me to write about, please leave a comment.</p>
<h4 id="heading-other-articles">Other Articles</h4>
<p>Here are other articles I have written that you might want to read.</p>
<p><a target="_blank" href="https://medium.freecodecamp.org/how-to-add-internationalization-to-a-vue-application-d9cfdcabb03b"><strong>How to add Internationalization to a Vue Application</strong></a><br><a target="_blank" href="https://medium.freecodecamp.org/how-to-add-internationalization-to-a-vue-application-d9cfdcabb03b">_¡Hola! Bonjour. Ciao. 你好. Here is how you add internationalization to Vue._medium.freecodecamp.org</a><a target="_blank" href="https://medium.com/dailyjs/instantiation-patterns-in-javascript-8fdcf69e8f9b"><strong>Instantiation Patterns in JavaScript</strong></a><br><a target="_blank" href="https://medium.com/dailyjs/instantiation-patterns-in-javascript-8fdcf69e8f9b">_Instantiation patterns are ways to create something in JavaScript. JavaScript provides four different methods to create…_medium.com</a><a target="_blank" href="https://hackernoon.com/here-are-5-layouts-that-you-can-make-with-flexbox-6ca1e941f33d"><strong>Here are 5 Layouts That You Can Make With FlexBox</strong></a><br><a target="_blank" href="https://hackernoon.com/here-are-5-layouts-that-you-can-make-with-flexbox-6ca1e941f33d">_The CSS Flexible Box Layout — Flexbox — provides a simple solution to the design and layout problems designers and…_hackernoon.com</a></p>
<p><a target="_blank" href="https://twitter.com/ratracegrad"><strong>Follow Me On Twitter!</strong></a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to build an SPA using Vue.js, Vuex, Vuetify, and Firebase: use Vuex and access the API ]]>
                </title>
                <description>
                    <![CDATA[ By Jennifer Bland Part 3: learn how to use Vuex and access the API to get your recipes Meal Prep application Learn how to create a meal delivery website using Vue.js, Vuex, Vue Router, and Firebase. This is part three of my four-part series on build... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-an-spa-using-vue-js-vuex-vuetify-and-firebase-use-vuex-and-access-the-api-f8036aa464ad/</link>
                <guid isPermaLink="false">66c35037f41767c3c96bad03</guid>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ vue ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Vue.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Vuex ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 26 Nov 2018 17:35:14 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*_oxBC3QDl02cB2MDOzGXZg.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jennifer Bland</p>
<h4 id="heading-part-3-learn-how-to-use-vuex-and-access-the-api-to-get-your-recipes">Part 3: learn how to use Vuex and access the API to get your recipes</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/lOmsmx05ec8WAJBTU8q3WNVuDZpRrQvfJ3wr" alt="Image" width="800" height="411" loading="lazy">
<em>Meal Prep application</em></p>
<p>Learn how to create a meal delivery website using Vue.js, Vuex, Vue Router, and Firebase.</p>
<p>This is part three of my four-part series on building a Vue application. Here is a list of all the parts:</p>
<p><a target="_blank" href="https://medium.com/p/838b40721a07">Part 1: Installing Vue and Building an SPA using Vuetify and Vue Router</a></p>
<p><a target="_blank" href="https://medium.com/p/fc5bd065fe18">Part 2: Using Vue Router</a></p>
<p><a target="_blank" href="https://medium.com/p/f8036aa464ad">Part 3: Using Vuex and accessing API</a></p>
<p><a target="_blank" href="https://medium.com/p/d9932d1e4365">Part 4: Using Firebase for Authentication</a></p>
<h3 id="heading-recap">Recap</h3>
<p>In the first part of this series, we created our Vue application using the Vue CLI. Also, we added Vuetify to the app. We used Vuetify to style our home page.</p>
<p>In the second part, we used Vue Router to add navigation between the different pages of our app. We added components for all the pages in our application.</p>
<h3 id="heading-accessing-the-api">Accessing the API</h3>
<p>We are building an SPA e-commerce website that sells meal delivery services. In order for this website to work, then we need recipes to create our meals. To generate our recipes we will use the <a target="_blank" href="https://www.edamam.com/">API from Edamam</a>. The Edamam recipe API contains 1.7+ million nutritionally analyzed recipes. The API allows you to filter recipes by diets. This is what we need since we will want to show recipes based on which diet the user has selected.</p>
<h4 id="heading-create-an-account-with-edamam">Create an account with Edamam</h4>
<p>The first step is to create your account with edamam. They provide a free account and that is what you want to sign up for. Click this link to go to the Edamam website. Click the <code>sign up</code> button for the Recipe Search API.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/o9BfUZEWOVODUChoaEo2CYOyFjFZarFOmHfY" alt="Image" width="800" height="395" loading="lazy">
<em>Edamam API Homepage</em></p>
<p>Next, you will be presented with three different levels that you can sign up for. We are going to use the free Developer tier. Click the <code>start now</code> button in the developer option.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ii1jZHksVpG738nDLymTnVNzw3SN27ZeG6G1" alt="Image" width="800" height="381" loading="lazy">
<em>Sign up for the free Developer account</em></p>
<p>You will be presented with a sign-up form. Complete the form.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/R80fRLGgShgTjiBleULB4ShCqda8p5vhRtBi" alt="Image" width="662" height="501" loading="lazy">
<em>Sign-up form</em></p>
<p>After completing the form you will be prompted to log in to your account. When you are logged in to your account, you will be asked to choose the API you need. Instead of clicking on any of the selection, instead, go to the menu and select <code>Get an API key now!</code></p>
<p>You should see your Recipe Search API key. <em>(NOTE: if you do not have a key then click the <code>create a new application</code> button to create one.)</em> Click on the view button to see the details of your API key. You will have an Application ID and Application Keys. You will need these to access the API for your website.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/wO28Vq5Uy3LHNuYngzH2BIT5BqiSGdHl6Lay" alt="Image" width="800" height="322" loading="lazy">
<em>API Keys needed to access Edamam</em></p>
<h4 id="heading-creating-menu-page">Creating Menu Page</h4>
<p>The menu page is where we will show recipes for each of the three diets we are supporting. These recipes will be retrieved from the Edamam API service.</p>
<p>The first thing we want to do is for the user to select a diet. We can do this by re-using the HomePlans component. We will modify the component to add a button to each diet for users to select. When visitors to the website click on a button they will see the recipes for that diet. <strong>But</strong> we do not want these buttons to be shown when the component is shown on the home page. So we are going to take care of this.</p>
<p>Open up the HomePlans component. Below the <code>v-card-text</code> section, we are going to add a <code>v-card-actions</code> section. This section will contain the button for users to select the plan. Here is what we are adding to each <code>v-card</code> in this component.</p>
<pre><code>&lt;v-card-actions v-<span class="hljs-keyword">if</span>=<span class="hljs-string">"['menu'].includes($route.name)"</span>&gt;    &amp;lt;v-btn outline block color=<span class="hljs-string">"green"</span> @click=<span class="hljs-string">"showRecipes('vegan')"</span>&gt;Select This Plan&lt;<span class="hljs-regexp">/v-btn&gt;&lt;/</span>v-card-actions&gt;
</code></pre><p>For each <code>v-card-actions</code> section, we will have a button. The button has the props of outline and block set. The button will call the method <code>showRecipes</code> when you click on the button. The method is passed a parameter with the text for the selected diet. Make sure you change this to reflect the selected diet. Here is what the template for the <code>HomePlans</code> component looks like now:</p>
<pre><code>&lt;template&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-container</span> <span class="hljs-attr">grid-list-lg</span>&gt;</span>        <span class="hljs-symbol">&amp;lt;</span>v-layout row&gt;            <span class="hljs-symbol">&amp;lt;</span>v-flex xs12 class="text-xs-center display-1 font-weight-black my-5"&gt;Available Meal Plans<span class="hljs-tag">&lt;/<span class="hljs-name">v-flex</span>&gt;</span></span>        &lt;<span class="hljs-regexp">/v-layout&gt;        &lt;v-layout row wrap&gt;            &lt;v-flex xs12 sm12 md4&gt;                &lt;v-card&gt;                    &lt;v-responsive&gt;                        &lt;v-img src="http:/</span><span class="hljs-regexp">/source.unsplash.com/</span>hjCA3ecCXAQ<span class="hljs-string">" height="</span><span class="hljs-number">500</span>px<span class="hljs-string">"&gt;                            &lt;v-container fill-height fluid&gt;                                &lt;v-layout fill-height&gt;                                    &lt;v-flex xs12 align-end flexbox&gt;                                        &lt;span class="</span>headline white--text<span class="hljs-string">"&gt;KETO&lt;/span&gt;                                    &lt;/v-flex&gt;                                &lt;/v-layout&gt;                            &lt;/v-container&gt;                        &lt;/v-img&gt;                    &lt;/v-responsive&gt;</span>
</code></pre><pre><code>                    &lt;v-card-text&gt;                        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"headline mb-0"</span>&gt;</span>Keto<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>The Keto diet is a high-fat, adequate-protein, low-carbohydrate diet. The diet forces the body to burn fats rather than carbohydrates by putting the body into ketosis.                            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>                    &lt;/v-card-text&gt;
</code></pre><pre><code>                    &lt;v-card-actions&gt;                        &amp;lt;v-btn outline block color=<span class="hljs-string">"green"</span> @click=<span class="hljs-string">"showRecipes('keto')"</span>&gt;Select This Plan&lt;<span class="hljs-regexp">/v-btn&gt;                    &lt;/</span>v-card-actions&gt;                &lt;<span class="hljs-regexp">/v-card&gt;            &lt;/</span>v-flex&gt;
</code></pre><pre><code>            &lt;v-flex xs12 sm12 md4&gt;                <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-card</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-responsive</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"http://source.unsplash.com/6S27S6pZ6o0"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"500px"</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">v-container</span> <span class="hljs-attr">fill-height</span> <span class="hljs-attr">fluid</span>&gt;</span>                                <span class="hljs-tag">&lt;<span class="hljs-name">v-layout</span> <span class="hljs-attr">fill-height</span>&gt;</span>                                    <span class="hljs-tag">&lt;<span class="hljs-name">v-flex</span> <span class="hljs-attr">xs12</span> <span class="hljs-attr">align-end</span> <span class="hljs-attr">flexbox</span>&gt;</span>                                        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"headline white--text"</span>&gt;</span>PALEO<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>                                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-flex</span>&gt;</span>                                <span class="hljs-tag">&lt;/<span class="hljs-name">v-layout</span>&gt;</span>                            <span class="hljs-tag">&lt;/<span class="hljs-name">v-container</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">v-img</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-responsive</span>&gt;</span></span>
</code></pre><pre><code>                    &lt;v-card-text&gt;                        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"headline mb-0"</span>&gt;</span>Paleo<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>The Paleo diet requires the sole or predominant consumption of foods presumed to have been the only foods available to or consumed by humans during the Paleolithic era.                            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>                    &lt;/v-card-text&gt;
</code></pre><pre><code>                    &lt;v-card-actions&gt;                        &amp;lt;v-btn outline block color=<span class="hljs-string">"green"</span> @click=<span class="hljs-string">"showRecipes('paleo')"</span>&gt;Select This Plan&lt;<span class="hljs-regexp">/v-btn&gt;                    &lt;/</span>v-card-actions&gt;                &lt;<span class="hljs-regexp">/v-card&gt;            &lt;/</span>v-flex&gt;
</code></pre><pre><code>            &lt;v-flex xs12 sm12 md4&gt;                <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-card</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-responsive</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"http://source.unsplash.com/1SPu0KT-Ejg"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"500px"</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">v-container</span> <span class="hljs-attr">fill-height</span> <span class="hljs-attr">fluid</span>&gt;</span>                                <span class="hljs-tag">&lt;<span class="hljs-name">v-layout</span> <span class="hljs-attr">fill-height</span>&gt;</span>                                    <span class="hljs-tag">&lt;<span class="hljs-name">v-flex</span> <span class="hljs-attr">xs12</span> <span class="hljs-attr">align-end</span> <span class="hljs-attr">flexbox</span>&gt;</span>                                        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"headline white--text"</span>&gt;</span>VEGAN<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>                                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-flex</span>&gt;</span>                                <span class="hljs-tag">&lt;/<span class="hljs-name">v-layout</span>&gt;</span>                            <span class="hljs-tag">&lt;/<span class="hljs-name">v-container</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">v-img</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-responsive</span>&gt;</span></span>
</code></pre><pre><code>                    &lt;v-card-text&gt;                        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"headline mb-0"</span>&gt;</span>Vegan<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>The vegan diet abstains from the use of animal products. The vegan diet does not consume meat, diary products, eggs or any all other animal-derived ingredients.                            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>                    &lt;/v-card-text&gt;
</code></pre><pre><code>                    &lt;v-card-actions&gt;                        &amp;lt;v-btn outline block color=<span class="hljs-string">"green"</span> @click=<span class="hljs-string">"showRecipes('vegan')"</span>&gt;Select This Plan&lt;<span class="hljs-regexp">/v-btn&gt;                    &lt;/</span>v-card-actions&gt;                &lt;<span class="hljs-regexp">/v-card&gt;            &lt;/</span>v-flex&gt;
</code></pre><pre><code>        &lt;<span class="hljs-regexp">/v-layout&gt;    &lt;/</span>v-container&gt;&lt;/template&gt;
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/421O0SuqauyfGkdPCpuDfGAhNVhZ0ChvI-Bm" alt="Image" width="800" height="503" loading="lazy">
<em>Select This Plan button added to HomePlans component</em></p>
<p>Now that we have added the button, we want to hide it on the home page and show it on the menu page. To do this we are going to combine the <code>v-if</code> directive and the name we assigned to each route.</p>
<p>In the <code>router.js</code> file, we added our routes. Routes is an array of objects. Each object has a <code>path</code>, <code>name</code> and <code>component</code>. We can use the array <code>includes</code> method to check if the current route is home. Here is what we will add to each <code>v-card-actions</code> sections:</p>
<pre><code>&lt;v-card-actions v-<span class="hljs-keyword">if</span>=<span class="hljs-string">"['menu'].includes($route.name)"</span>&gt;    &amp;lt;v-btn outline block color=<span class="hljs-string">"green"</span> @click=<span class="hljs-string">"showRecipes('vegan')"</span>&gt;Select This Plan&lt;<span class="hljs-regexp">/v-btn&gt;&lt;/</span>v-card-actions&gt;
</code></pre><p>Here is what the template for the HomePlans component looks like now:</p>
<pre><code>&lt;template&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-container</span> <span class="hljs-attr">grid-list-lg</span>&gt;</span>        <span class="hljs-symbol">&amp;lt;</span>v-layout row&gt;            <span class="hljs-symbol">&amp;lt;</span>v-flex xs12 class="text-xs-center display-1 font-weight-black my-5"&gt;Available Meal Plans<span class="hljs-tag">&lt;/<span class="hljs-name">v-flex</span>&gt;</span></span>        &lt;<span class="hljs-regexp">/v-layout&gt;        &lt;v-layout row wrap&gt;            &lt;v-flex xs12 sm12 md4&gt;                &lt;v-card&gt;                    &lt;v-responsive&gt;                        &lt;v-img src="http:/</span><span class="hljs-regexp">/source.unsplash.com/</span>hjCA3ecCXAQ<span class="hljs-string">" height="</span><span class="hljs-number">500</span>px<span class="hljs-string">"&gt;                            &lt;v-container fill-height fluid&gt;                                &lt;v-layout fill-height&gt;                                    &lt;v-flex xs12 align-end flexbox&gt;                                        &lt;span class="</span>headline white--text<span class="hljs-string">"&gt;KETO&lt;/span&gt;                                    &lt;/v-flex&gt;                                &lt;/v-layout&gt;                            &lt;/v-container&gt;                        &lt;/v-img&gt;                    &lt;/v-responsive&gt;</span>
</code></pre><pre><code>                    &lt;v-card-text&gt;                        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"headline mb-0"</span>&gt;</span>Keto<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>The Keto diet is a high-fat, adequate-protein, low-carbohydrate diet. The diet forces the body to burn fats rather than carbohydrates by putting the body into ketosis.                            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>                    &lt;/v-card-text&gt;
</code></pre><pre><code>                    &lt;v-card-actions v-<span class="hljs-keyword">if</span>=<span class="hljs-string">"['menu'].includes($route.name)"</span>&gt;                        &amp;lt;v-btn outline block color=<span class="hljs-string">"green"</span> @click=<span class="hljs-string">"showRecipes('keto')"</span>&gt;Select This Plan&lt;<span class="hljs-regexp">/v-btn&gt;                    &lt;/</span>v-card-actions&gt;                &lt;<span class="hljs-regexp">/v-card&gt;            &lt;/</span>v-flex&gt;
</code></pre><pre><code>            &lt;v-flex xs12 sm12 md4&gt;                <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-card</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-responsive</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"http://source.unsplash.com/6S27S6pZ6o0"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"500px"</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">v-container</span> <span class="hljs-attr">fill-height</span> <span class="hljs-attr">fluid</span>&gt;</span>                                <span class="hljs-tag">&lt;<span class="hljs-name">v-layout</span> <span class="hljs-attr">fill-height</span>&gt;</span>                                    <span class="hljs-tag">&lt;<span class="hljs-name">v-flex</span> <span class="hljs-attr">xs12</span> <span class="hljs-attr">align-end</span> <span class="hljs-attr">flexbox</span>&gt;</span>                                        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"headline white--text"</span>&gt;</span>PALEO<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>                                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-flex</span>&gt;</span>                                <span class="hljs-tag">&lt;/<span class="hljs-name">v-layout</span>&gt;</span>                            <span class="hljs-tag">&lt;/<span class="hljs-name">v-container</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">v-img</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-responsive</span>&gt;</span></span>
</code></pre><pre><code>                    &lt;v-card-text&gt;                        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"headline mb-0"</span>&gt;</span>Paleo<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>The Paleo diet requires the sole or predominant consumption of foods presumed to have been the only foods available to or consumed by humans during the Paleolithic era.                            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>                    &lt;/v-card-text&gt;
</code></pre><pre><code>                    &lt;v-card-actions v-<span class="hljs-keyword">if</span>=<span class="hljs-string">"['menu'].includes($route.name)"</span>&gt;                        &amp;lt;v-btn outline block color=<span class="hljs-string">"green"</span> @click=<span class="hljs-string">"showRecipes('paleo')"</span>&gt;Select This Plan&lt;<span class="hljs-regexp">/v-btn&gt;                    &lt;/</span>v-card-actions&gt;                &lt;<span class="hljs-regexp">/v-card&gt;            &lt;/</span>v-flex&gt;
</code></pre><pre><code>            &lt;v-flex xs12 sm12 md4&gt;                <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-card</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-responsive</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"http://source.unsplash.com/1SPu0KT-Ejg"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"500px"</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">v-container</span> <span class="hljs-attr">fill-height</span> <span class="hljs-attr">fluid</span>&gt;</span>                                <span class="hljs-tag">&lt;<span class="hljs-name">v-layout</span> <span class="hljs-attr">fill-height</span>&gt;</span>                                    <span class="hljs-tag">&lt;<span class="hljs-name">v-flex</span> <span class="hljs-attr">xs12</span> <span class="hljs-attr">align-end</span> <span class="hljs-attr">flexbox</span>&gt;</span>                                        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"headline white--text"</span>&gt;</span>VEGAN<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>                                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-flex</span>&gt;</span>                                <span class="hljs-tag">&lt;/<span class="hljs-name">v-layout</span>&gt;</span>                            <span class="hljs-tag">&lt;/<span class="hljs-name">v-container</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">v-img</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-responsive</span>&gt;</span></span>
</code></pre><pre><code>                    &lt;v-card-text&gt;                        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"headline mb-0"</span>&gt;</span>Vegan<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>                            <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>The vegan diet abstains from the use of animal products. The vegan diet does not consume meat, diary products, eggs or any all other animal-derived ingredients.                            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>                    &lt;/v-card-text&gt;
</code></pre><pre><code>                    &lt;v-card-actions v-<span class="hljs-keyword">if</span>=<span class="hljs-string">"['menu'].includes($route.name)"</span>&gt;                        &amp;lt;v-btn outline block color=<span class="hljs-string">"green"</span> @click=<span class="hljs-string">"showRecipes('vegan')"</span>&gt;Select This Plan&lt;<span class="hljs-regexp">/v-btn&gt;                    &lt;/</span>v-card-actions&gt;                &lt;<span class="hljs-regexp">/v-card&gt;            &lt;/</span>v-flex&gt;
</code></pre><pre><code>        &lt;<span class="hljs-regexp">/v-layout&gt;    &lt;/</span>v-container&gt;&lt;/template&gt;
</code></pre><h4 id="heading-getting-recipes">Getting Recipes</h4>
<p>When a user clicks on the <code>Add This Plan</code> button it calls the method <code>showRecipes</code>. Let's create this method now. This method will retrieve recipes from the Edamam API. First, we need to install axios by entering this command at the terminal:</p>
<pre><code>npm install axios
</code></pre><p>To use axios we will need to import it. In the script section of the HomePlans component import it with this command:</p>
<pre><code><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
</code></pre><p>Next, in the export default section of the HomePlans component, we will add our method.</p>
<p><em>NOTE: I am going to show you how to use axios in a component to get data from an API. BUT then we are going to ditch this code and use Vuex. So from here to the title <strong>Using Vuex</strong> is code that we will not use it in the final version of our application — but I wanted to show it so you understand it.</em></p>
<p>The method is called <code>showRecipes</code> and takes one parameter called <code>plan</code>. In this method, I will use axios to get 10 recipes from Edamam based on the diet plan selected. The axios call will be a GET to the URL <code>[https://api.edamam.com/search](https://api.edamam.com/search.)</code><a target="_blank" href="https://api.edamam.com/search.">.</a></p>
<p>According to the Edamam API documentation, we are required to use a param called <code>q</code> that contains our query string. We will set this value to the plan parameter that is passed into our method. The documentation also requires us to supply params for app_id and app_key. You will need to set these values to your keys you were assigned when you signed up for the Edamam API.</p>
<p>There are two more params we will use. They are <code>to</code> and <code>from</code>. These params specify the start and end of the number of recipes that are returned. For demo purposes, we will limit it to return just the first 10 recipes.</p>
<p>Our axios call will either succeed or fail. Axios provides a promise so we can use <code>.then</code> and <code>.catch</code> to handle both success and failure. If the call succeeds we want to set the recipes data value equal to the <code>hits</code> array that is returned from Edamam. All responses from axios are contained in the <code>data</code> object. We account for this by first assigning response to response.data. Next, we assign recipes to <code>response.hits</code>.</p>
<p>What if the axios call fails? Well, we use the <code>.catch</code> of the promise to handle a failure. In this case, all we want to do is set recipes to an empty array.</p>
<p>Here is what the method looks like:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {    <span class="hljs-attr">name</span>: <span class="hljs-string">'HomePlans'</span>,    data() {        <span class="hljs-keyword">return</span> {            <span class="hljs-attr">recipes</span>: []        };    },    <span class="hljs-attr">methods</span>: {        showRecipes(plan) {            axios                .get(<span class="hljs-string">'https://api.edamam.com/search'</span>, {                    <span class="hljs-attr">params</span>: {                        <span class="hljs-attr">q</span>: plan,                        <span class="hljs-attr">app_id</span>: <span class="hljs-string">'5b6623d5'</span>,                        <span class="hljs-attr">app_key</span>: <span class="hljs-string">'46674aa2193dbb7b88ffd897331e661a'</span>,                        <span class="hljs-attr">from</span>: <span class="hljs-number">0</span>,                        <span class="hljs-attr">to</span>: <span class="hljs-number">9</span>                    }                })                .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> {                    response = response.data;                    <span class="hljs-built_in">this</span>.recipes = response.hits;                })                .catch(<span class="hljs-function">() =&gt;</span> {                    <span class="hljs-built_in">this</span>.recipes = [];                });        }    }};
</code></pre><h3 id="heading-using-vuex">Using Vuex</h3>
<p>Now we have worked ourselves into a pickle with our code. We originally had a component that showed a picture, title and short description of a diet. We added a button to it to get recipes. Now if we keep going then we will need to add functionality to display the recipes that we retrieved from the Edamam API.</p>
<p>I really don’t want all this functionality placed into this component. I want it to just display the image, title, short description and button. But by having the button in the component, I need a way to handle when the user clicks the button. I also need a way to display recipes. To do this I am going to move the functionality of handling the button click to Vuex.</p>
<p>Vuex is a state management library for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion. Vuex consists of:</p>
<ul>
<li>The state, which is the source of truth that drives our app;</li>
<li>The mutations, which change the value of the state;</li>
<li>The actions, which are the possible ways the state could change in reaction to user inputs from the view.</li>
</ul>
<p>When we created our application using the Vue CLI 3 we specified that we would be using Vuex. As a result, the CLI created the file <code>store.js</code> in the src folder for us.</p>
<p><code>State</code> will contain the recipes. We will use an <code>actions</code> to make the API call to retrieve recipes. A <code>mutations</code> will be used to update the variable <code>recipe</code> in <code>state</code> with the recipes returned from the <code>actions</code> call.</p>
<p>Open up the <code>store.js</code> file. First, add a new recipes variable in state and assign it to an empty array. Also add a variable called apiUrl. This variable will contain the url for our API call. It should look like this:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">new</span> Vuex.Store({    <span class="hljs-attr">state</span>: {        <span class="hljs-attr">recipes</span>: [],        <span class="hljs-attr">apiUrl</span>: <span class="hljs-string">'https://api.edamam.com/search'</span>    },    <span class="hljs-attr">mutations</span>: {},    <span class="hljs-attr">actions</span>: {}});
</code></pre><p>Next, we are going to create an action called <code>getRecipes</code>. This action will use axios to get recipes from the API. To use axios we will need to import it. At the top of the file, there are two import commands. Place this after them:</p>
<pre><code><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
</code></pre><p>Earlier I showed you using promises with the axios call. Now I am going to show you how to do the same call using async / await. The method getRecipes will have to be prefixed with <code>async</code>. Inside the method, we have a try catch block. Inside the try block, we will set a variable <code>response</code> to the data returned from the axios call. We put await in front of the axios call. If the call succeeds we will call the mutation <code>setRecipes</code>. SetRecipes will change the state to set recipes to the array of recipes returned from the API call.</p>
<p>If the API call fails it will end up in the catch block. In this scenario, we call the same mutation but pass it an empty array. Here is what the store.js should look like:</p>
<pre><code><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;<span class="hljs-keyword">import</span> Vuex <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex'</span>;<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;Vue.use(Vuex);<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">new</span> Vuex.Store({    <span class="hljs-attr">state</span>: {        <span class="hljs-attr">recipes</span>: [],        <span class="hljs-attr">apiUrl</span>: <span class="hljs-string">'https://api.edamam.com/search'</span>    },    <span class="hljs-attr">mutations</span>: {        setRecipes(state, payload) {            state.recipes = payload;        }    },    <span class="hljs-attr">actions</span>: {        <span class="hljs-keyword">async</span> getRecipes({ state, commit }, plan) {            <span class="hljs-keyword">try</span> {                <span class="hljs-keyword">let</span> response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">`<span class="hljs-subst">${state.apiUrl}</span>`</span>, {                    <span class="hljs-attr">params</span>: {                        <span class="hljs-attr">q</span>: plan,                        <span class="hljs-attr">app_id</span>: <span class="hljs-string">'&lt;yourAppIdHere&gt;'</span>,                        <span class="hljs-attr">app_key</span>: <span class="hljs-string">'&lt;yourAppKeyHere&gt;'</span>,                        <span class="hljs-attr">from</span>: <span class="hljs-number">0</span>,                        <span class="hljs-attr">to</span>: <span class="hljs-number">9</span>                    }                });                commit(<span class="hljs-string">'setRecipes'</span>, response.data.hits);            } <span class="hljs-keyword">catch</span> (error) {                commit(<span class="hljs-string">'setRecipes'</span>, []);            }        }    }});
</code></pre><h4 id="heading-updating-homeplans-component">Updating HomePlans Component</h4>
<p>Let’s go back to our HomePlans component and clean it up. We can remove the import axios line of code. We can remove the <code>data()</code> object. In the <code>showRecipes</code> method, you can delete all of the code. We now need just one line of code to call our action in our Vuex store. To call an action in Vuex you use a <code>dispatch</code>. This is the one line of code for our <code>showRecipes</code> method:</p>
<pre><code><span class="hljs-built_in">this</span>.$store.dispatch(<span class="hljs-string">'getRecipes'</span>, plan);
</code></pre><p>Here is what our HomePlans component looks like:</p>
<pre><code>&lt;template&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-container</span> <span class="hljs-attr">grid-list-lg</span>&gt;</span>        <span class="hljs-symbol">&amp;lt;</span>v-layout row&gt;            <span class="hljs-symbol">&amp;lt;</span>v-flex xs12 class="text-xs-center display-1 font-weight-black my-5"&gt;Available Meal Plans<span class="hljs-tag">&lt;/<span class="hljs-name">v-flex</span>&gt;</span></span>        &lt;<span class="hljs-regexp">/v-layout&gt;        &lt;v-layout row wrap&gt;            &lt;v-flex xs12 sm12 md4&gt;                &lt;v-card&gt;                    &lt;v-responsive&gt;                        &lt;v-img src="http:/</span><span class="hljs-regexp">/source.unsplash.com/</span>hjCA3ecCXAQ<span class="hljs-string">" height="</span><span class="hljs-number">500</span>px<span class="hljs-string">"&gt;                            &lt;v-container fill-height fluid&gt;                                &lt;v-layout fill-height&gt;                                    &lt;v-flex xs12 align-end flexbox&gt;                                        &lt;span class="</span>headline white--text<span class="hljs-string">"&gt;KETO&lt;/span&gt;                                    &lt;/v-flex&gt;                                &lt;/v-layout&gt;                            &lt;/v-container&gt;                        &lt;/v-img&gt;                    &lt;/v-responsive&gt;                    &lt;v-card-text&gt;                        &lt;div&gt;                            &lt;h3 class="</span>headline mb<span class="hljs-number">-0</span><span class="hljs-string">"&gt;Keto&lt;/h3&gt;                            &lt;div&gt;The Keto diet is a high-fat, adequate-protein, low-carbohydrate diet. The diet forces the body to burn fats rather than carbohydrates by putting the body into ketosis.                            &lt;/div&gt;                        &lt;/div&gt;                    &lt;/v-card-text&gt;                    &lt;v-card-actions v-if="</span>[<span class="hljs-string">'menu'</span>].includes($route.name)<span class="hljs-string">"&gt;                        &lt;v-btn outline block color="</span>green<span class="hljs-string">" @click="</span>showRecipes(<span class="hljs-string">'keto'</span>)<span class="hljs-string">"&gt;Select This Plan&lt;/v-btn&gt;                    &amp;lt;/v-card-actions&gt;                &lt;/v-card&amp;gt;            &lt;/v-flex&gt;            &lt;v-flex xs12 sm12 md4&gt;                &lt;v-card&gt;                    &lt;v-responsive&gt;                        &lt;v-img src="</span>http:<span class="hljs-comment">//source.unsplash.com/6S27S6pZ6o0" height="500px"&gt;                            &lt;v-container fill-height fluid&gt;                                &lt;v-layout fill-height&gt;                                    &lt;v-flex xs12 align-end flexbox&gt;                                        &lt;span class="headline white--text"&gt;PALEO&lt;/span&gt;                                    &lt;/v-flex&gt;                                &lt;/v-layout&gt;                            &lt;/v-container&gt;                        &lt;/v-img&gt;                    &lt;/v-responsive&gt;                    &lt;v-card-text&gt;                        &lt;div&gt;                            &lt;h3 class="headline mb-0"&gt;Paleo&lt;/h3&gt;                            &lt;div&gt;The Paleo diet requires the sole or predominant consumption of foods presumed to have been the only foods available to or consumed by humans during the Paleolithic era.                            &lt;/div&gt;                        &lt;/div&amp;gt;                    &lt;/v-card-text&gt;                    &lt;v-card-actions v-if="['menu'].includes($route.name)"&gt;                        &lt;v-btn outline block color="green" @click="showRecipes('paleo')"&gt;Select This Plan&lt;/v-btn&gt;                    &lt;/v-card-actions&gt;                &lt;/v-card&amp;gt;            &lt;/v-flex&gt;            &lt;v-flex xs12 sm12 md4&amp;gt;                &lt;v-card&gt;                    &lt;v-responsive&gt;                        &lt;v-img src="http://source.unsplash.com/1SPu0KT-Ejg" height="500px"&gt;                            &lt;v-container fill-height fluid&gt;                                &lt;v-layout fill-height&gt;                                    &lt;v-flex xs12 align-end flexbox&gt;                                        &lt;span class="headline white--text"&gt;VEGAN&lt;/span&gt;                                    &lt;/v-flex&gt;                                &lt;/v-layout&gt;                            &lt;/v-container&gt;                        &lt;/v-img&gt;                    &lt;/v-responsive&gt;                    &lt;v-card-text&gt;                        &lt;div&gt;                            &lt;h3 class="headline mb-0"&gt;Vegan&lt;/h3&gt;                            &lt;div&gt;The vegan diet abstains from the use of animal products. The vegan diet does not consume meat, diary products, eggs or any all other animal-derived ingredients.                            &lt;/div&gt;                        &lt;/div&gt;                    &lt;/v-card-text&gt;                    &lt;v-card-actions v-if="['menu'].includes($route.name)"&gt;                        &lt;v-btn outline block color="green" @click="showRecipes('vegan')"&gt;Select This Plan&lt;/v-btn&gt;                    &lt;/v-card-actions&gt;                &lt;/v-card&gt;            &lt;/v-flex&gt;        &lt;/v-layout&gt;    &lt;/v-container&gt;&lt;/template&gt;&lt;script&gt;export default {    name: 'HomePlans',    methods: {        showRecipes(plan) {            this.$store.dispatch('getRecipes', plan);        }    }};&lt;/script&gt;&lt;style scoped&gt;&lt;/style&gt;</span>
</code></pre><h4 id="heading-displaying-recipes">Displaying Recipes</h4>
<p>We have used Vuex to get recipes from the API. We store the array of recipes in the Vuex store. Now we need a new component that will be used to display the recipes. Inside your components folder create a new file called <code>MealRecipes.vue</code>.</p>
<p>In this new component, we will add a computed value for recipes. This computed variable will get its value from Vuex store. Its value will be set to the value of <code>recipes</code> in <code>state</code>. This is what it looks like:</p>
<pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {    <span class="hljs-attr">name</span>: <span class="hljs-string">'MealRecipes'</span>,    <span class="hljs-attr">computed</span>: {        recipes() {            <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.$store.state.recipes;        }    }};&lt;/script&gt;
</code></pre><p>We need to update the template in this component to display our recipes. Vuetify provides a grid-list which creates spacing between items displayed on the page. We will use this functionality by placing it on the v-container that is the root element in our template. Like this:</p>
<pre><code>&lt;v-container grid-list-lg&gt;
</code></pre><pre><code>&lt;/v-container&gt;
</code></pre><p>Inside the <code>v-container</code> we will have a <code>v-layout</code>. Inside the <code>v-layout</code> we will have a <code>v-flex</code>. We set the layout on the v-layout to be <code>row</code>. We will also add <code>wrap</code>. On the <code>v-flex</code> we will loop through all the recipes in the array and display them. So we need a <code>v-for</code> . Vue now requires you to have an index for every v-for loop. We add an <code>idx</code> and set that to the <code>key</code>. Here is what our MealRecipes component looks like so far.</p>
<pre><code>&lt;v-container grid-list-lg&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-layout</span> <span class="hljs-attr">row</span> <span class="hljs-attr">wrap</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">v-flex</span> <span class="hljs-attr">xs12</span> <span class="hljs-attr">sm6</span> <span class="hljs-attr">md6</span> <span class="hljs-attr">lg4</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"(item, idx) in recipes"</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">"idx"</span>&gt;</span>        <span class="hljs-tag">&lt;/<span class="hljs-name">v-flex</span>&gt;</span>    <span class="hljs-tag">&lt;/<span class="hljs-name">v-layout</span>&gt;</span></span><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-container</span>&gt;</span></span>
</code></pre><p>We will use the Vuetify <code>v-card</code> to display each recipe. This is very similar to the layout we used for the <code>HomePlans</code> component. We will display an image for the recipe, a title and a list of ingredients.</p>
<p>The API call returns an array of recipes. If you look at one entry in the array you will notice that it has a recipe object. Inside that object, we will find a URL for the recipe image, title, and list of ingredients. The API returns two different arrays for the ingredients. The one we will use is the one in the ingredientLines array.</p>
<p>Here is what the <code>MealRecipes</code> component looks like:</p>
<pre><code>&lt;template&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-container</span> <span class="hljs-attr">grid-list-lg</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">v-layout</span> <span class="hljs-attr">row</span> <span class="hljs-attr">wrap</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">v-flex</span> <span class="hljs-attr">xs12</span> <span class="hljs-attr">sm6</span> <span class="hljs-attr">md6</span> <span class="hljs-attr">lg4</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"(item, idx) in recipes"</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">"idx"</span>&gt;</span>                <span class="hljs-tag">&lt;<span class="hljs-name">v-card</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-responsive</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-img</span> <span class="hljs-attr">:src</span>=<span class="hljs-string">"item.recipe.image"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">v-img</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-responsive</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-card-text</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"title"</span>&amp;<span class="hljs-attr">gt</span>;{{<span class="hljs-attr">item.recipe.label</span>}}&lt;/<span class="hljs-attr">div</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"subheading"</span>&gt;</span>Ingredients<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">ul&amp;gt;</span>                            &lt;<span class="hljs-attr">li</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"(ingredient, i) in item.recipe.ingredientLines"</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">"i"</span>&gt;</span>{{ingredient}}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-card-text</span>&gt;</span>                <span class="hljs-tag">&lt;/<span class="hljs-name">v-card</span>&gt;</span>            <span class="hljs-tag">&lt;/<span class="hljs-name">v-flex</span>&gt;</span>        <span class="hljs-tag">&lt;/<span class="hljs-name">v-layout</span>&gt;</span>    <span class="hljs-tag">&lt;/<span class="hljs-name">v-container</span>&gt;</span></span>&lt;<span class="hljs-regexp">/template&gt;&lt;script&gt;export default {    name: 'MealRecipes',    computed: {        recipes() {            return this.$store.state.recipes;        }    }};&lt;/</span>script&gt;<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">scoped</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>
</code></pre><p>Now that we have the component finished, we need to use it inside the <code>Menu.vue</code> component. Open the <code>Menu.vue</code> component. Import the MealRecipes component with this command:</p>
<pre><code><span class="hljs-keyword">import</span> MealRecipes <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/MealRecipes'</span>;
</code></pre><p>Add it to the components like this:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {    <span class="hljs-attr">name</span>: <span class="hljs-string">'Menu'</span>,    <span class="hljs-attr">components</span>: {        HomePlans,        MealRecipes    }};
</code></pre><p>In the template add mealRecipes below homePlans. Here is what <code>Menu.vue</code> should look like:</p>
<pre><code>&lt;template&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">home-plans</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">home-plans</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">meal-recipes</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">meal-recipes&amp;gt;</span>    &lt;/<span class="hljs-attr">div</span>&amp;<span class="hljs-attr">gt</span>;&amp;<span class="hljs-attr">lt</span>;/<span class="hljs-attr">template</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"><span class="hljs-keyword">import</span> HomePlans <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/HomePlans'</span>;<span class="hljs-keyword">import</span> MealRecipes <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/MealRecipes'</span>;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {    <span class="hljs-attr">name</span>: <span class="hljs-string">'Menu'</span>,    <span class="hljs-attr">components</span>: {        HomePlans,        MealRecipes    }};</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">scoped</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>
</code></pre><p>Start the application with the command <code>npm run serve</code> in the terminal. Open your browser to <a target="_blank" href="http://localhost:8080">http://localhost:8080</a> and you will see the application running. Click on menu in the navigation. Then click on any of the diet plans. You should see a list of recipes like this:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/jN9C9yDOw9ebushF2n2yYuksBX4jEAD4PLmR" alt="Image" width="800" height="523" loading="lazy">
<em>List of recipes</em></p>
<p>I want to make two quick changes to how the recipes are styled. First I want to add some more spacing between the recipe title and ingredients. Second I want to add a button to the bottom of every recipe for a person to order.</p>
<p>So open up the <code>MealRecipes</code> component. For the title, I already have a class of <code>title</code>. I am going to add to that a value of <code>my-3</code>. This is equivalent to adding margin-top and margin-bottom to the title. This lets the title offset from the image and the ingredients.</p>
<p>Last change I want to make is to add a button. Inside the <code>v-card</code> and below the <code>v-card-text</code> we will add a <code>v-card-actions</code>. Inside that, we will add a button. We will use the default button with a green color. By default, Vuetify makes the text in buttons black in color. We can change that to white by adding the <code>dark</code> directive. Here is our button:</p>
<pre><code>&lt;v-card-actions&gt;    &amp;lt;v-btn color=<span class="hljs-string">"green"</span> dark&gt;Order&lt;<span class="hljs-regexp">/v-btn&gt;&lt;/</span>v-card-actions&gt;
</code></pre><p>Here is our MealRecipes component:</p>
<pre><code>&lt;template&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">v-container</span> <span class="hljs-attr">grid-list-lg</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">v-layout</span> <span class="hljs-attr">row</span> <span class="hljs-attr">wrap</span>&gt;</span>            <span class="hljs-tag">&lt;<span class="hljs-name">v-flex</span> <span class="hljs-attr">xs12</span> <span class="hljs-attr">sm6</span> <span class="hljs-attr">md6</span> <span class="hljs-attr">lg4</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"(item, idx) in recipes"</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">"idx"</span>&gt;</span>                <span class="hljs-tag">&lt;<span class="hljs-name">v-card</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-responsive</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-img</span> <span class="hljs-attr">:src</span>=<span class="hljs-string">"item.recipe.image"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">v-img</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-responsive</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-card-text</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"title my-5"</span>&amp;<span class="hljs-attr">gt</span>;{{<span class="hljs-attr">item.recipe.label</span>}}&lt;/<span class="hljs-attr">div</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"subheading"</span>&gt;</span>Ingredients<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">ul&amp;gt;</span>                            &lt;<span class="hljs-attr">li</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"(ingredient, i) in item.recipe.ingredientLines"</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">"i"</span>&gt;</span>{{ingredient}}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>                        <span class="hljs-tag">&lt;/<span class="hljs-name">ul&amp;gt;</span>                    &lt;/<span class="hljs-attr">v-card-text</span>&gt;</span>                    <span class="hljs-tag">&lt;<span class="hljs-name">v-card-actions</span>&gt;</span>                        <span class="hljs-tag">&lt;<span class="hljs-name">v-btn</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"green"</span> <span class="hljs-attr">dark</span>&gt;</span>Order<span class="hljs-tag">&lt;/<span class="hljs-name">v-btn</span>&gt;</span>                    <span class="hljs-tag">&lt;/<span class="hljs-name">v-card-actions</span>&gt;</span>                <span class="hljs-tag">&lt;/<span class="hljs-name">v-card</span>&gt;</span>            <span class="hljs-tag">&lt;/<span class="hljs-name">v-flex</span>&gt;</span>        <span class="hljs-tag">&lt;/<span class="hljs-name">v-layout</span>&gt;</span>    <span class="hljs-tag">&lt;/<span class="hljs-name">v-container</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span></span>&amp;lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {    <span class="hljs-attr">name</span>: <span class="hljs-string">'MealRecipes'</span>,    <span class="hljs-attr">computed</span>: {        recipes() {            <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.$store.state.recipes;        }    }};&lt;<span class="hljs-regexp">/script&gt;&lt;style scoped&gt;&lt;/</span>style&gt;
</code></pre><h3 id="heading-get-the-code">Get the Code</h3>
<p>Even though this is a 4-part series, you can get the <a target="_blank" href="https://github.com/ratracegrad/meal-prep">finished code in my GitHub account.</a> Please help me out and <strong>star the repo</strong> when you get the code.</p>
<h3 id="heading-summary">Summary</h3>
<p>In this part of this series, you have learned:</p>
<ul>
<li>What is Vuex</li>
<li>How to get recipes from an API</li>
<li>How to use Axios with promises and async / await</li>
<li>How to call actions in Vuex store</li>
<li>How to mutate state in Vuex</li>
</ul>
<h3 id="heading-whats-next">What’s Next</h3>
<p>In the next part of this series, we will cover Firebase for authentication. Firebase allows you to develop an application without having to write server-side code.</p>
<p>If you enjoyed this article please clap for it. If you think somebody else would benefit from this article please share it with them.</p>
<p>If you have any questions or find anything wrong with the code, please leave a comment. If there are other topics you would like for me to write about, please leave a comment.</p>
<h4 id="heading-other-articles">Other Articles</h4>
<p>Here are other articles I have written that you might want to read.</p>
<p><a target="_blank" href="https://hackernoon.com/here-are-5-layouts-that-you-can-make-with-flexbox-6ca1e941f33d"><strong>Here are 5 Layouts That You Can Make With FlexBox</strong></a><br><a target="_blank" href="https://hackernoon.com/here-are-5-layouts-that-you-can-make-with-flexbox-6ca1e941f33d">_The CSS Flexible Box Layout — Flexbox — provides a simple solution to the design and layout problems designers and…_hackernoon.com</a><a target="_blank" href="https://hackernoon.com/mastering-css-series-shape-outside-44d626270b25"><strong>Think outside the box with CSS shape-outside</strong></a><br><a target="_blank" href="https://hackernoon.com/mastering-css-series-shape-outside-44d626270b25">_CSS is based off a box model. If you have an image that is a circle that you want to wrap text around, it will wrap…_hackernoon.com</a><a target="_blank" href="https://medium.freecodecamp.org/why-company-culture-is-important-to-your-career-as-a-software-engineer-5a590bc44621"><strong>Why Company Culture is Important to Your Career as a Software Engineer</strong></a><br><a target="_blank" href="https://medium.freecodecamp.org/why-company-culture-is-important-to-your-career-as-a-software-engineer-5a590bc44621">_The impact of a company’s culture is reflected in a company’s ability to achieve their goals and productivity levels…_medium.freecodecamp.org</a></p>
<p><a target="_blank" href="https://twitter.com/ratracegrad"><strong>Follow Me On Twitter!</strong></a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Vue Handbook: a thorough introduction to Vue.js ]]>
                </title>
                <description>
                    <![CDATA[ Get this post in PDF/ePub/MOBI format at vuehandbook.com Vue is a very popular JavaScript front-end framework, one that’s experiencing a huge amount of growth. It is simple, tiny (~24KB), and very performant. It feels different from all the other Ja... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-vue-handbook-a-thorough-introduction-to-vue-js-1e86835d8446/</link>
                <guid isPermaLink="false">66bb5ac6092af3d2a3aa9c0d</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Vue.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Vuex ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Flavio Copes ]]>
                </dc:creator>
                <pubDate>Thu, 05 Jul 2018 16:45:07 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*Nzc4LiAlVXl8ic9T6v31zw.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <blockquote>
<p>Get this post in PDF/ePub/MOBI format at <a target="_blank" href="https://vuehandbook.com">vuehandbook.com</a></p>
</blockquote>
<p>Vue is a very popular JavaScript front-end framework, one that’s experiencing a huge amount of growth.</p>
<p>It is simple, tiny (~24KB), and very performant. It feels different from all the other JavaScript front-end frameworks and view libraries. Let’s find out why.</p>
<h3 id="heading-first-what-is-a-javascript-front-end-framework">First, what is a JavaScript front-end framework?</h3>
<p>If you’re unsure what a JavaScript framework is, Vue is the perfect first encounter with one.</p>
<p>A JavaScript framework helps us to create modern applications. Modern JavaScript applications are mostly used on the Web, but also power a lot of Desktop and Mobile applications.</p>
<p>Until the early 2000s, browsers didn’t have the capabilities they have now. They were a lot less powerful, and building complex applications inside them was not feasible performance-wise. The tooling was not even something that people thought about.</p>
<p>Everything changed when Google unveiled <a target="_blank" href="https://www.google.com/maps">Google Maps</a> and <a target="_blank" href="https://www.google.com/gmail">GMail</a>, two applications that ran inside the browser. <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX/Getting_Started">Ajax</a> made asynchronous network requests possible. Over time, developers started building on top of the Web platform, while engineers worked on the platform itself — browsers, the Web standards, the browser APIs, and the JavaScript language.</p>
<p>Libraries like <a target="_blank" href="https://jquery.com/">jQuery</a> and <a target="_blank" href="https://mootools.net/">Mootools</a> were the first big projects that built upon JavaScript and were hugely popular for a while. They basically provided a nicer API to interact with the browser and provided workarounds for bugs and inconsistencies among the various browsers.</p>
<p>Frameworks like <a target="_blank" href="http://backbonejs.org/">Backbone</a>, <a target="_blank" href="https://www.emberjs.com/">Ember</a>, <a target="_blank" href="http://knockoutjs.com/">Knockout</a>, and <a target="_blank" href="https://angularjs.org/">AngularJS</a> were the first wave of modern JavaScript frameworks.</p>
<p>The second wave, which is the current one, has <a target="_blank" href="https://reactjs.org/">React</a>, <a target="_blank" href="https://angular.io/">Angular</a>, and <a target="_blank" href="https://vuejs.org/">Vue</a> as its main actors.</p>
<p>Note that jQuery, Ember and the other projects I mentioned are still being heavily used, actively maintained, and millions of websites rely on them.</p>
<p>That said, techniques and tools evolve, and as a JavaScript developer, you’re now likely to be required to know React, Angular or Vue rather than those older frameworks.</p>
<p>Frameworks abstract the interaction with the browser and the DOM. Instead of manipulating elements by referencing them in the DOM, we <a target="_blank" href="https://en.wikipedia.org/wiki/Declarative_programming">declaratively</a> define and interact with them, at a higher level.</p>
<p>Using a framework is like using the <a target="_blank" href="https://en.wikipedia.org/wiki/C_(programming_language)">C programming language</a> instead of using the <a target="_blank" href="https://en.wikipedia.org/wiki/Assembly_language">Assembly language</a> to write system programs. It’s like using a computer to write a document instead of using a typewriter. It’s like having a self-driving car instead of driving the car yourself.</p>
<p>Well, not that far, but you get the idea. Instead of using low-level APIs offered by the browser to manipulate elements, and building hugely complex systems to write an application, you use tools built by very smart people that make our life easier.</p>
<h3 id="heading-the-popularity-of-vue">The popularity of Vue</h3>
<p>How popular is Vue.js?</p>
<p>Vue had:</p>
<ul>
<li>7,600 stars on GitHub in 2016</li>
<li>36,700 stars on GitHub in 2017</li>
</ul>
<p>and it has more than 100,000+ stars on GitHub, as of June 2018.</p>
<p>Its <a target="_blank" href="https://www.npmjs.com/">npm</a> download count is growing every day, and now it’s at ~350,000 downloads per week.</p>
<p>I would say Vue is very popular, given those numbers.</p>
<p>In relative terms, it has approximately the same numbers of GitHub stars as React, which was born years before.</p>
<p>Numbers are not everything, of course. The impression I have of Vue is that developers <strong>love</strong> it.</p>
<p>A key point in time of the rise of Vue has been the adoption in the Laravel ecosystem, a hugely popular PHP web application framework. But since then it has become widespread among many other development communities.</p>
<h4 id="heading-why-developers-love-vue">Why developers love Vue</h4>
<p>First, Vue is called a progressive framework.</p>
<p>This means that it adapts to the needs of the developer. Other frameworks require a complete buy-in from a developer or team and often want you to rewrite an existing application because they require some specific set of conventions. Vue happily lands inside your app with a simple <code>script</code> tag to start with, and it can grow along with your needs, spreading from 3 lines to managing your entire view layer.</p>
<p>You don’t need to know about <a target="_blank" href="https://webpack.js.org/">webpack</a>, <a target="_blank" href="https://babeljs.io/">Babel</a>, npm or anything to get started with Vue. But when you’re ready, Vue makes it simple for you to rely on them.</p>
<p>This is one great selling point, especially in the current ecosystem of JavaScript front-end frameworks and libraries that tend to alienate newcomers and also experienced developers that feel lost in the ocean of possibilities and choices.</p>
<p>Vue.js is probably the most approachable front-end framework around. Some people call Vue the <strong>new jQuery</strong>, because it easily gets in the application via a script tag, and gradually gains space from there. Think of it as a compliment, since jQuery dominated the Web in the past few years, and it still does its job on a huge number of sites.</p>
<p>Vue was built by picking the best ideas of frameworks like Angular, React and Knockout, and by cherry-picking the best choices those frameworks made. And by excluding some less brilliant ones, it kind of started as a “best-of” set and grew from there.</p>
<h4 id="heading-where-does-vuejs-position-itself-in-the-frameworks-landscape">Where does Vue.js position itself in the frameworks landscape?</h4>
<p>The two elephants in the room, when talking about web development, are React and Angular. How does Vue position itself relative to those two big and popular frameworks?</p>
<p>Vue was created by Evan You when he was working at Google on AngularJS (Angular 1.0) apps. It was born out of a need to create more performant applications. Vue picked some of the Angular templating syntax, but removed the opinionated, complex stack that Angular required, and made it very performant.</p>
<p>The new Angular (Angular 2.0) also solved many of the AngularJS issues, but in very different ways. It also requires a buy-in to <a target="_blank" href="https://www.typescriptlang.org/">TypeScript</a> which not all developers enjoy using (or want to learn).</p>
<p>What about React? Vue took many good ideas from React, most importantly the Virtual DOM. But Vue implements it with some sort of automatic dependency management. This tracks which components are affected by a change of the state so that only those components are re-rendered when that state property changes.</p>
<p>In React, on the other hand, when a part of the state that affects a component changes, the component will be re-rendered. By default all its children will be re-rendered as well. To avoid this you need to use the <code>shouldComponentUpdate</code> method of each component and determine if that component should be re-rendered. This gives Vue a bit of an advantage in terms of ease of use, and out of the box performance gains.</p>
<p>One big difference with React is <a target="_blank" href="https://reactjs.org/docs/introducing-jsx.html">JSX</a>. While you can technically use JSX in Vue, it’s not a popular approach and instead the <a target="_blank" href="https://vuejs.org/v2/guide/syntax.html">templating system</a> is used. Any HTML file is a valid Vue template. JSX is very different than HTML, and has a learning curve for people on the team that might only need to work with the HTML part of the app, like designers.</p>
<p>Vue templates are very similar to <a target="_blank" href="http://mustache.github.io/">Mustache</a> and <a target="_blank" href="https://handlebarsjs.com/">Handlebars</a> (although they differ in terms of flexibility). As such, they are more familiar to developers that already used frameworks like Angular and Ember.</p>
<p>The official state management library, <a target="_blank" href="https://vuex.vuejs.org/">Vuex</a>, follows the Flux architecture and is somewhat similar to <a target="_blank" href="https://redux.js.org/">Redux</a> in its concepts. Again, this is part of the positive things about Vue, which saw this good pattern in React and borrowed it for its ecosystem. And while you can use Redux with Vue, Vuex is specifically tailored for Vue and its inner workings.</p>
<p>Vue is flexible, but the fact that the core team maintains two packages that are very important for any web app (like routing and state management) makes it a lot less fragmented than React. For example: <code>vue-router</code> and <code>vuex</code> are key to the success of Vue.</p>
<p>You don't need to choose or worry if that library you chose is going to be maintained in the future and will keep up with framework updates. Since they are official, they are the canonical go-to libraries for their niche (but you can choose to use what you like, of course).</p>
<p>One thing that puts Vue in a different bucket compared to React and Angular is that Vue is an <strong>indie</strong> project: it’s not backed by a huge corporation like Facebook or Google.</p>
<p>Instead, it’s completely backed by the community, which fosters development through donations and sponsors. This makes sure the roadmap of Vue is not driven by a single company’s agenda.</p>
<h3 id="heading-your-first-vue-app">Your first Vue App</h3>
<p>If you’ve never created a Vue.js application, I am going to guide you through the task of creating one so that you understand how it works.</p>
<h4 id="heading-first-example">First example</h4>
<p>First I’ll go through the most basic example of using Vue.</p>
<p>You create an HTML file which contains:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"example"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{{ hello }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/vue"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
        <span class="hljs-keyword">new</span> Vue({
            <span class="hljs-attr">el</span>: <span class="hljs-string">'#example'</span>,
            <span class="hljs-attr">data</span>: { <span class="hljs-attr">hello</span>: <span class="hljs-string">'Hello World!'</span> }
        })
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>and you open it in the browser. That’s your first Vue app! The page should show a “Hello World!” message.</p>
<p>I put the script tags at the end of the body so that they are executed in order after the DOM is loaded.</p>
<p>What this code does is instantiate a new Vue app, linked to the <code>#example</code> element as its template. It's defined using a CSS selector usually, but you can also pass in an <code>HTMLElement</code>.</p>
<p>Then, it associates that template to the <code>data</code> object. That is a special object that hosts the data we want Vue to render.</p>
<p>In the template, the special <code>{{ }}</code> tag indicates that this is some part of the template that's dynamic, and its content should be looked up in the Vue app data.</p>
<p>You can see this example on <a target="_blank" href="https://codepen.io/flaviocopes/pen/YLoLOp">CodePen</a>.</p>
<p>CodePen is a little different from using a plain HTML file, and you need to configure it to point to the Vue library location in the Pen settings:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Qa8s2ayB3DhhE3dRKv4SFowGd8xHDvEeSlL4" alt="Image" width="800" height="725" loading="lazy"></p>
<h4 id="heading-second-example-the-vue-cli-default-app">Second example: the Vue CLI default app</h4>
<p>Let’s level up the game a little bit. The next app we’re going to build is already done, and it’s the Vue CLI default application.</p>
<p>What is the Vue CLI? It’s a command line utility that helps to speed up development by scaffolding an application skeleton for you, with a sample app in place.</p>
<p>There are two ways you can get this application:</p>
<p><strong>Use the Vue CLI locally</strong></p>
<p>The first is to install the Vue CLI on your computer and run the command:</p>
<pre><code class="lang-sh">vue create &lt;enter the app name&gt;
</code></pre>
<p><strong>Use CodeSandbox</strong></p>
<p>A simpler way, without having to install anything, is to go to <a target="_blank" href="https://codesandbox.io/s/vue">CodeSandbox</a>. The link opens the Vue CLI default application.</p>
<p>CodeSandbox is a cool code editor that allows you build apps in the cloud. You can use any npm package, and can easily integrate with <a target="_blank" href="https://zeit.co/now">Zeit Now</a> for an easy deployment and with <a target="_blank" href="https://github.com/">GitHub</a> to manage versioning.</p>
<p>Whether you chose to use the Vue CLI locally, or go through CodeSandbox, let’s inspect that Vue app in detail.</p>
<h3 id="heading-the-files-structure">The files structure</h3>
<p>Beside <code>package.json</code>, which contains the configuration, these are the files contained in the initial project structure:</p>
<ul>
<li><code>index.html</code></li>
<li><code>src/App.vue</code></li>
<li><code>src/main.js</code></li>
<li><code>src/assets/logo.png</code></li>
<li><code>src/components/HelloWorld.vue</code></li>
</ul>
<h4 id="heading-indexhtml"><code>index.html</code></h4>
<p>The <code>index.html</code> file is the main app file.</p>
<p>In the body it includes just one simple element: <code>&lt;div id="app"&gt;</code>. This is the element the Vue application we’ll use to attach to the DOM.</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width,initial-scale=1.0"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>CodeSandbox Vue<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- built files will be auto injected --&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h4 id="heading-srcmainjs"><code>src/main.js</code></h4>
<p>This is the main JavaScript file that drives our app.</p>
<p>We first import the Vue library and the App component from <code>App.vue</code>.</p>
<p>We set <code>productionTip</code> to <code>false</code>, to avoid Vue outputting a “you’re in development mode” tip in the console.</p>
<p>Next, we create the Vue instance, by assigning it to the DOM element identified by <code>#app</code>, which we defined in <code>index.html</code>, and we tell it to use the App component.</p>
<pre><code class="lang-js"><span class="hljs-comment">// The Vue build version to load with the `import` command</span>
<span class="hljs-comment">// (runtime-only or standalone) has been set in webpack.base.conf with an alias.</span>
<span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>

Vue.config.productionTip = <span class="hljs-literal">false</span>

<span class="hljs-comment">/* eslint-disable no-new */</span>
<span class="hljs-keyword">new</span> Vue({
  <span class="hljs-attr">el</span>: <span class="hljs-string">'#app'</span>,
  <span class="hljs-attr">components</span>: { App },
  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;App/&gt;'</span>
})
</code></pre>
<h4 id="heading-srcappvue"><code>src/App.vue</code></h4>
<p><code>App.vue</code> is a Single File Component. It contains three chunks of code: HTML, CSS, and JavaScript.</p>
<p>This might seem weird at first, but Single File Components are a great way to create self-contained components that have all they need in a single file.</p>
<p>We have the markup, the JavaScript that is going to interact with it, and style that’s applied to it, which can be scoped or not. In this case, it’s not scoped, and it’s just outputting that CSS which is applied like regular CSS to the page.</p>
<p>The interesting part lies in the <code>script</code> tag.</p>
<p>We import a component from the <code>components/HelloWorld.vue</code> file, which we'll describe later.</p>
<p>This component is going to be referenced in our component. It’s a dependency. We are going to output this code</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"25%"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./assets/logo.png"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">HelloWorld</span>/&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>from this component, which you see references the <code>HelloWorld</code> component. Vue will automatically insert that component inside this placeholder.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"25%"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./assets/logo.png"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">HelloWorld</span>/&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
<span class="hljs-keyword">import</span> HelloWorld <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/HelloWorld'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-attr">name</span>: <span class="hljs-string">'App'</span>,
  <span class="hljs-attr">components</span>: {
    HelloWorld
  }
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
<span class="hljs-selector-id">#app</span> {
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Avenir'</span>, Helvetica, Arial, sans-serif;
  <span class="hljs-attribute">-webkit-font-smoothing</span>: antialiased;
  <span class="hljs-attribute">-moz-osx-font-smoothing</span>: grayscale;
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#2c3e50</span>;
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">60px</span>;
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<h4 id="heading-srccomponentshelloworldvue"><code>src/components/HelloWorld.vue</code></h4>
<p>Here’s the <code>HelloWorld</code> component, which is included by the App component.</p>
<p>This component outputs a set of links, along with a message.</p>
<p>Remember above we talked about CSS in App.vue, which was not scoped? The <code>HelloWorld</code> component has scoped CSS.</p>
<p>You can easily determine it by looking at the <code>style</code> tag. If it has the <code>scoped</code> attribute, then it's scoped: <code>&lt;style scop</code>ed&gt;</p>
<p>This means that the generated CSS will be targeting the component uniquely, via a class that’s applied by Vue transparently. You don’t need to worry about this, and you know the CSS won’t <strong>leak</strong> to other parts of the page.</p>
<p>The message the component outputs is stored in the <code>data</code> property of the Vue instance, and outputted in the template as <code>{{ msg }}</code>.</p>
<p>Anything that’s stored in <code>data</code> is reachable directly in the template via its own name. We didn't need to say <code>data.msg</code>, just <code>msg</code>.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hello"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{{ msg }}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Essential Links<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">"https://vuejs.org"</span>
          <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
        &gt;</span>
          Core Docs
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">"https://forum.vuejs.org"</span>
          <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
        &gt;</span>
          Forum
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">"https://chat.vuejs.org"</span>
          <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
        &gt;</span>
          Community Chat
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">"https://twitter.com/vuejs"</span>
          <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
        &gt;</span>
          Twitter
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">"http://vuejs-templates.github.io/webpack/"</span>
          <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
        &gt;</span>
          Docs for This Template
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Ecosystem<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">"http://router.vuejs.org/"</span>
          <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
        &gt;</span>
          vue-router
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">"http://vuex.vuejs.org/"</span>
          <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
        &gt;</span>
          vuex
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">"http://vue-loader.vuejs.org/"</span>
          <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
        &gt;</span>
          vue-loader
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">"https://github.com/vuejs/awesome-vue"</span>
          <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
        &gt;</span>
          awesome-vue
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-attr">name</span>: <span class="hljs-string">'HelloWorld'</span>,
  data() {
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">msg</span>: <span class="hljs-string">'Welcome to Your Vue.js App'</span>
    }
  }
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Add "scoped" attribute to limit CSS to this component only --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">scoped</span>&gt;</span><span class="css">
<span class="hljs-selector-tag">h1</span>,
<span class="hljs-selector-tag">h2</span> {
  <span class="hljs-attribute">font-weight</span>: normal;
}
<span class="hljs-selector-tag">ul</span> {
  <span class="hljs-attribute">list-style-type</span>: none;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
}
<span class="hljs-selector-tag">li</span> {
  <span class="hljs-attribute">display</span>: inline-block;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> <span class="hljs-number">10px</span>;
}
<span class="hljs-selector-tag">a</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#42b983</span>;
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<h4 id="heading-run-the-app">Run the app</h4>
<p>CodeSandbox has a cool preview functionality. You can run the app and edit anything in the source to have it immediately reflected in the preview.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ZWfaVoQWEm4HzD0RNcS2osp8NpIPz-G5Vq5P" alt="Image" width="800" height="629" loading="lazy"></p>
<h3 id="heading-the-vue-cli">The Vue CLI</h3>
<p>CodeSandbox is very cool for online coding and working without having to setup Vue locally. A great way to work locally is by setting up the Vue CLI (command line interface). Let’s find out more about it.</p>
<p>In the previous example, I introduced an example project based on the Vue CLI. What’s the Vue CLI exactly, and how does it fit in the Vue ecosystem? Also, how do we setup a Vue CLI-based project locally? Let’s find out!</p>
<p><strong>Note:</strong> There is a huge rework of the CLI going on right now, going from version 2 to 3. While not yet stable, I will describe version 3, because it’s a huge improvement over version 2, and quite different.</p>
<h4 id="heading-installation">Installation</h4>
<p>The Vue CLI is a command line utility, and you install it globally using npm:</p>
<pre><code>npm install -g @vue/cli
</code></pre><p>or using Yarn:</p>
<pre><code>yarn <span class="hljs-built_in">global</span> add @vue/cli
</code></pre><p>Once you do so, you can invoke the <code>vue</code> command.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/F1uuQW81iw1WZNOiUn0xnLOagFi637vPDUfd" alt="Image" width="800" height="423" loading="lazy"></p>
<h4 id="heading-what-does-the-vue-cli-provide">What does the Vue CLI provide?</h4>
<p>The CLI is essential for rapid Vue.js development.</p>
<p>Its main goal is to make sure all the tools you need are working along, to perform what you need, and abstracts away all the nitty-gritty configuration details that using each tool in isolation would require.</p>
<p>It can perform an initial project setup and scaffolding.</p>
<p>It’s a flexible tool. Once you create a project with the CLI, you can go and tweak the configuration, without having to <strong>eject</strong> your application (like you’d do with <code>create-react-app</code>).</p>
<p>When you eject from <code>create-react-app</code> you can update and tweak what you want, but you can’t rely on the cool features that <code>create-react-app</code> provides.</p>
<p>You can configure anything and still be able to upgrade with ease.</p>
<p>After you create and configure the app, it acts as a runtime dependency tool, built on top of Webpack.</p>
<p>The first encounter with the CLI is when creating a new Vue project.</p>
<h4 id="heading-how-to-use-the-cli-to-create-a-new-vue-project">How to use the CLI to create a new Vue project</h4>
<p>The first thing you’re going to do with the CLI is to create a Vue app:</p>
<pre><code>vue create example
</code></pre><p>The cool thing is that it’s an interactive process. You need to pick a preset. By default, there is one preset that provides Babel and <a target="_blank" href="https://eslint.org/">ESLint</a> integration:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/FL4mTLZqzhKkAYL2FB507Tx1Hkdtnl0y5cgu" alt="Image" width="800" height="402" loading="lazy"></p>
<p>I’m going to press the down arrow ⬇️ and manually choose the features I want:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/mkF3jMMCGluqmQ3hX3bGbCxhfXcwvWVNjWLi" alt="Image" width="800" height="434" loading="lazy"></p>
<p>Press <code>space</code> to enable one of the things you need, and then press <code>enter</code> to go on. Since I chose <code>Linter / Formatter</code>, Vue CLI prompts me for the configuration. I chose <code>ESLint + Prettier</code> since that's my favorite setup:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/bYwN2mfgTuJNxiiHBSNjnJQADZQvFR0TErhK" alt="Image" width="800" height="434" loading="lazy"></p>
<p>Next thing is choosing how to apply linting. I choose <code>Lint on save</code>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/dcQmjoykCaJG7pevG5Yc-6A43eVYUkCbTxn7" alt="Image" width="800" height="434" loading="lazy"></p>
<p>Next up: testing. Vue CLI lets me choose between the two most popular unit testing solutions: <a target="_blank" href="https://mochajs.org/">Mocha + Chai</a> and <a target="_blank" href="https://jestjs.io/">Jest</a>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/lIdwYkOgcllnAJRVZOoKIxZ49ikNFoQjYtSV" alt="Image" width="800" height="434" loading="lazy"></p>
<p>Vue CLI asks me where to put all the configuration: in the <code>package.json</code> file, or in dedicated configuration files, one for each tool. I chose the latter.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/dN4W4ZALKh7Xz1D8ac7ebXpGdTPVGpzdujcc" alt="Image" width="800" height="434" loading="lazy"></p>
<p>Next, Vue CLI asks me if I want to save these presets, and allows me to pick them as a choice the next time I use Vue CLI to create a new app. It’s a very convenient feature, as having a quick setup with all my preferences is a complexity reliever:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/X6rbmBloyRnQbdwrFQwtYeChdqxzQRpOJYfl" alt="Image" width="800" height="434" loading="lazy"></p>
<p>Vue CLI then asks me if I prefer using <a target="_blank" href="https://yarnpkg.com/lang/en/">Yarn</a> or NPM:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/vbEmq0oYaGFjDtjL9D2QaUZ6t5omf0fjZTJM" alt="Image" width="800" height="434" loading="lazy"></p>
<p>This is the last thing it asks me, and then it goes on to download the dependencies and create the Vue app:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Q52LD-RGQm9dHXMyWikiI5fMyESB7vRJqe1h" alt="Image" width="800" height="1008" loading="lazy"></p>
<h4 id="heading-how-to-start-the-newly-created-vue-cli-application">How to start the newly created Vue CLI application</h4>
<p>Vue CLI has created the app for us, and we can go in the <code>example</code> folder and run <code>yarn serve</code> to start up our first app in development mode:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/iegqNiWWJaunJi-KFTV93EKuODc4njdfLRuf" alt="Image" width="800" height="839" loading="lazy"></p>
<p>The starter example application source contains a few files, including <code>package.json</code>:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/FuI7nmJ2NAtesloTZrh3eJL-aa0ceCCr68wQ" alt="Image" width="800" height="821" loading="lazy"></p>
<p>This is where all the CLI commands are defined, including <code>yarn serve</code>, which we used a minute ago. The other commands are</p>
<ul>
<li><code>yarn build</code>, to start a production build</li>
<li><code>yarn lint</code>, to run the linter</li>
<li><code>yarn test:unit</code>, to run the unit tests</li>
</ul>
<p>I will describe the sample application generated by Vue CLI in a separate tutorial.</p>
<h4 id="heading-git-repository">Git repository</h4>
<p>Notice the <code>master</code> word in the lower-left corner of VS Code? That's because Vue CLI automatically creates a repository, and makes the first commit. So we can jump right in, change things, and we know what we changed:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/4IHrGo6U-xkz4aeVXf3S06AYzIk0lAZJ6t6y" alt="Image" width="800" height="360" loading="lazy"></p>
<p>This is pretty cool. How many times do you dive in and change things, only to realize, when you want to commit the result, that you didn’t commit the initial state?</p>
<h4 id="heading-use-a-preset-from-the-command-line">Use a preset from the command line</h4>
<p>You can skip the interactive panel and instruct Vue CLI to use a particular preset:</p>
<pre><code>vue create -p favourite example<span class="hljs-number">-2</span>
</code></pre><h4 id="heading-where-presets-are-stored">Where presets are stored</h4>
<p>Presets are stored in the <code>.vuejs</code> file in your home directory. Here's mine after creating the first "favorite" preset:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"useTaobaoRegistry"</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">"packageManager"</span>: <span class="hljs-string">"yarn"</span>,
  <span class="hljs-attr">"presets"</span>: {
    <span class="hljs-attr">"favourite"</span>: {
      <span class="hljs-attr">"useConfigFiles"</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-attr">"plugins"</span>: {
        <span class="hljs-attr">"@vue/cli-plugin-babel"</span>: {},
        <span class="hljs-attr">"@vue/cli-plugin-eslint"</span>: {
          <span class="hljs-attr">"config"</span>: <span class="hljs-string">"prettier"</span>,
          <span class="hljs-attr">"lintOn"</span>: [
            <span class="hljs-string">"save"</span>
          ]
        },
        <span class="hljs-attr">"@vue/cli-plugin-unit-jest"</span>: {}
      },
      <span class="hljs-attr">"router"</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-attr">"vuex"</span>: <span class="hljs-literal">true</span>
    }
  }
}
</code></pre>
<h4 id="heading-plugins">Plugins</h4>
<p>As you can see from reading the configuration, a preset is basically a collection of plugins, with some optional configuration.</p>
<p>Once a project is created, you can add more plugins by using <code>vue add</code>:</p>
<pre><code>vue add @vue/cli-plugin-babel
</code></pre><p>All those plugins are used in the latest version available. You can force Vue CLI to use a specific version by passing the version property:</p>
<pre><code class="lang-json"><span class="hljs-string">"@vue/cli-plugin-eslint"</span>: {
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"^3.0.0"</span>
}
</code></pre>
<p>This is useful if a new version has a breaking change or a bug, and you need to wait a little bit before using it.</p>
<h4 id="heading-remotely-store-presets">Remotely store presets</h4>
<p>A preset can be stored in GitHub (or on other services) by creating a repository that contains a <code>preset.json</code> file, which contains a single preset configuration.</p>
<p>Extracted from the above, I made a sample <a target="_blank" href="https://github.com/flaviocopes/vue-cli-preset/blob/master/preset.json">preset</a> which contains this configuration:</p>
<pre><code>{  <span class="hljs-string">"useConfigFiles"</span>: <span class="hljs-literal">true</span>,  <span class="hljs-string">"plugins"</span>: {    <span class="hljs-string">"@vue/cli-plugin-babel"</span>: {},    <span class="hljs-string">"@vue/cli-plugin-eslint"</span>: {      <span class="hljs-string">"config"</span>: <span class="hljs-string">"prettier"</span>,      <span class="hljs-string">"lintOn"</span>: [        <span class="hljs-string">"save"</span>      ]    },    <span class="hljs-string">"@vue/cli-plugin-unit-jest"</span>: {}  },  <span class="hljs-string">"router"</span>: <span class="hljs-literal">true</span>,  <span class="hljs-string">"vuex"</span>: <span class="hljs-literal">true</span>}
</code></pre><p>It can be used to bootstrap a new application using:</p>
<pre><code>vue create --preset flaviocopes/vue-cli-preset example3
</code></pre><h3 id="heading-another-use-of-the-vue-cli-rapid-prototyping">Another use of the Vue CLI: rapid prototyping</h3>
<p>Up until now, I’ve explained how to use the Vue CLI to create a new project from scratch, with all the bells and whistles. But for really quick prototyping, you can create a really simple Vue application (even one that’s self-contained in a single .vue file) and serve that, without having to download all the dependencies in the <code>node_modules</code> folder.</p>
<p>How? First install the <code>cli-service-global</code> global package:</p>
<pre><code>npm install -g @vue/cli-service-<span class="hljs-built_in">global</span>
</code></pre><pre><code><span class="hljs-comment">//or</span>
</code></pre><pre><code>yarn <span class="hljs-built_in">global</span> add @vue/cli-service-<span class="hljs-built_in">global</span>
</code></pre><p>Create an app.vue file:</p>
<pre><code>&lt;template&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Hello world!<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>        <span class="hljs-tag">&lt;<span class="hljs-name">marquee</span>&gt;</span>Heyyy<span class="hljs-tag">&lt;/<span class="hljs-name">marquee</span>&gt;</span>    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>&lt;/template&gt;
</code></pre><p>and then run</p>
<pre><code>vue serve app.vue
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/pp3QTRAMwLtOnkhazBRgRrjYKnMEbnm1CbWL" alt="Image" width="811" height="618" loading="lazy">
<em>The standalone app</em></p>
<p>You can serve more organized projects, composed by JavaScript and HTML files as well. Vue CLI by default uses <code>main.js / index.js</code> as its entry point, and you can have a <code>package.json</code> and any tool configuration set up. <code>vue serve</code> will pick it up.</p>
<p>Since this uses global dependencies, it’s not an optimal approach for anything more than a demonstration or quick testing.</p>
<p>Running <code>vue build</code> will prepare the project for deployment in <code>dist/</code>, and will generate all the corresponding code (also for vendor dependencies).</p>
<h4 id="heading-webpack">Webpack</h4>
<p>Internally, Vue CLI uses Webpack, but the configuration is abstracted and we don’t even see the config file in our folder. You can still have access to it by calling <code>vue inspect</code>:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/dGT6I8Uq75505tD1Xj8wR-h7rO9ZvRby80cH" alt="Image" width="800" height="1008" loading="lazy"></p>
<h3 id="heading-the-vue-devtools">The Vue DevTools</h3>
<p>When you’re first experimenting with Vue, if you open the Browser Developer Tools, you will find this message: “Download the Vue Devtools extension for a better development experience: <a target="_blank" href="https://github.com/vuejs/vue-devtools">https://github.com/vuejs/vue-devtools</a>"</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/J-LJE-u3DphYF8pOpMnkCX9KoNz3fGp4OPea" alt="Image" width="800" height="392" loading="lazy">
<em>Hint to install the Vue devtools</em></p>
<p>This is a friendly reminder to install the Vue Devtools Extension. What’s that? Any popular framework has its own devtools extension, which generally adds a new panel to the browser developer tools that is much more specialized than the ones that the browser ships by default. In this case, the panel will let us inspect our Vue application and interact with it.</p>
<p>This tool will be an amazing help when building Vue apps. The developer tools can only inspect a Vue application when it’s in development mode. This makes sure no one can use them to interact with your production app — and will make Vue more performant, because it does not have to care about the Dev Tools.</p>
<p>Let’s install it!</p>
<p>There are 3 ways to install the Vue Dev Tools:</p>
<ul>
<li>on Chrome</li>
<li>on Firefox</li>
<li>as a standalone application</li>
</ul>
<p>Safari, Edge and other browsers are not supported with a custom extension, but using the standalone application you can debug a Vue.js app running in any browser.</p>
<h4 id="heading-install-on-chrome">Install on Chrome</h4>
<p>Go to this page on the Google Chrome <a target="_blank" href="https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd">Store</a> and click <code>**Add to Chrome**</code>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/uh0CFZPRsdnKFOY-OWWvQCN3UVcnh-0KXpfh" alt="Image" width="800" height="575" loading="lazy"></p>
<p>Go through the installation process:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/hAQZpBESrlkCeLeLJpzeiPdJs12mmFHLRq9s" alt="Image" width="800" height="575" loading="lazy"></p>
<p>The Vue.js devtools icon shows up in the toolbar. If the page does not have a Vue.js instance running, it’s grayed out.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/TaZntVatyBmsqqKsMjbGKn5nIuJikKLOJJyt" alt="Image" width="800" height="575" loading="lazy"></p>
<p>If Vue.js is detected, the icon has the Vue logo’s colors.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/xPbOBNuLCdCE28QiFevAcqFb06Oqk8tB31Zy" alt="Image" width="800" height="553" loading="lazy"></p>
<p>The icon does nothing except show us that there <strong>is</strong> a Vue.js instance. To use the devtools, we must open the Developer Tools panel, using “View → Developer → Developer Tools”, or <code>Cmd-Alt-i</code></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/td1gw01JZxVxAkHLGg9FKzIHz8UFhMhvr3gG" alt="Image" width="800" height="495" loading="lazy"></p>
<h4 id="heading-install-on-firefox">Install on Firefox</h4>
<p>You can find the Firefox dev tools extension in the Mozilla Add-ons <a target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/">store</a>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/y-G2Zcw62ZrkjMOe6ottwLy-z6onBxnZzOXm" alt="Image" width="800" height="608" loading="lazy"></p>
<p>Click “Add to Firefox” and the extension will be installed. As with Chrome, a grayed icon shows up in the toolbar</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/LQCCB8c2g0OsUmJZ20fYJBPbampJudlIPocv" alt="Image" width="800" height="608" loading="lazy"></p>
<p>And when you visit a site that has a Vue instance running, it will become green, and when we open the Dev Tools we will see a “Vue” panel:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/jFYMTGNEhrkxzzC6Grdb7zgXrnHrwuR-0AiI" alt="Image" width="800" height="528" loading="lazy"></p>
<h4 id="heading-install-the-standalone-app">Install the standalone app</h4>
<p>Alternatively, you can use the DevTools standalone app.</p>
<p>Simply install it using:</p>
<pre><code>npm install -g @vue/devtools
</code></pre><pre><code><span class="hljs-comment">//or</span>
</code></pre><pre><code>yarn <span class="hljs-built_in">global</span> add @vue/devtools
</code></pre><p>and run it by calling:</p>
<pre><code>vue-devtools
</code></pre><p>This will open the standalone Electron-based application.</p>
<p>Now, paste the script tag it shows you</p>
<pre><code>&lt;script src=<span class="hljs-string">"http://localhost:8098"</span>&gt;&lt;/script&gt;
</code></pre><p>inside the project <code>index.html</code> file, and wait for the app to be reloaded. It will automatically connect to the app.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ANnfWmlscUkP0RN9Pn-hSABLCOxzMJYvtuqw" alt="Image" width="800" height="624" loading="lazy"></p>
<h4 id="heading-how-to-use-the-developer-tools">How to use the Developer Tools</h4>
<p>As mentioned, the Vue DevTools can be activated by opening the Developer Tools in the browser and moving to the Vue panel.</p>
<p>Another option is to right-click on any element in the page, and choose “Inspect Vue component”:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/r4URIzj-Mm92WTnnl9iXMK18f8cIwmyICQ0m" alt="Image" width="796" height="524" loading="lazy"></p>
<p>When the Vue DevTools panel is open, we can navigate the components tree. When we choose a component from the list on the left, the right panel shows the props and data it holds:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/h55RK1azzd7gjON36Da9HdY-tpu8cuVMBs-3" alt="Image" width="800" height="495" loading="lazy"></p>
<p>On the top there are fourbuttons:</p>
<ul>
<li><strong>Components</strong> (the current panel), which lists all the component instances running in the current page. Vue can have multiple instances running at the same time. For example, it might manage your shopping cart widget and the slideshow, with separate, lightweight apps.</li>
<li><strong>Vuex</strong> is where you can inspect the state managed through Vuex.</li>
<li><strong>Events</strong> shows all the events emitted.</li>
<li><strong>Refresh</strong> reloads the devtools panel.</li>
</ul>
<p>Notice the small <code>= $vm0</code> text beside a component? It's a handy way to inspect a component using the Console. Pressing the "esc" key shows up the console in the bottom of the devtools, and you can type <code>$vm0</code> to access the Vue component:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/9fi396qPj8ajABDLnAoB77AkjDtLEJu-2okG" alt="Image" width="800" height="495" loading="lazy"></p>
<p>It’s very cool to inspect and interact with components without having to assign them to a global variable in the code.</p>
<h4 id="heading-filter-components">Filter components</h4>
<p>Start typing a component name, and the components tree will filter out the ones that don’t match.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/IdqSWwFMpvHVN125f7uIxue0Xp0ic-HJmBzX" alt="Image" width="800" height="376" loading="lazy"></p>
<h4 id="heading-select-a-component-in-the-page">Select a component in the page</h4>
<p>Click the <code>**Select component in the page**</code> button.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/RE969Y8eHdDn1rqHvj2OGfnEqthwHMVy37A-" alt="Image" width="48" height="40" loading="lazy">
<em>Select component in the page</em></p>
<p>You can hover over any component in the page with the mouse, click it, and it will be opened in the devtools.</p>
<h4 id="heading-format-components-names">Format components names</h4>
<p>You can choose to show components in camelCase or use dashes.</p>
<h4 id="heading-filter-inspected-data">Filter inspected data</h4>
<p>On the right panel, you can type any word to filter the properties that don’t match it.</p>
<h4 id="heading-inspect-dom">Inspect DOM</h4>
<p>Click the Inspect DOM button to be brought to the DevTools Elements inspector, with the DOM element generated by the component:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/YKTlyULN-MDOAg3R1KPA3tI27IqX5Q9ckIH4" alt="Image" width="800" height="384" loading="lazy">
<em>Inspect the DOM</em></p>
<h4 id="heading-open-in-editor">Open in editor</h4>
<p>Any user component (not framework-level components) has a button that opens it in your default editor. Very handy.</p>
<h3 id="heading-setup-vs-code-to-work-with-vue">Setup VS Code to work with Vue</h3>
<p><a target="_blank" href="https://code.visualstudio.com/">Visual Studio Code</a> is one of the most used code editors in the world right now. Editors have, like many software products, a cycle. Once <a target="_blank" href="https://macromates.com/">TextMate</a> was the favorite among developers, then it was <a target="_blank" href="https://www.sublimetext.com/">Sublime Text</a>, now it’s VS Code.</p>
<p>The cool thing about being popular is that people dedicate a lot of time to building plugins for everything they can imagine.</p>
<p>One such plugin is an awesome tool that can help us Vue.js developers.</p>
<h4 id="heading-vetur">Vetur</h4>
<p>It’s called Vetur, it’s hugely popular (more than 3 million downloads), and you can find it <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=octref.vetur">on the Visual Studio Marketplace</a>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/OOfHNunbiMBxokJsrmdrvWixSoDmaDdPRzxK" alt="Image" width="800" height="610" loading="lazy"></p>
<h4 id="heading-installing-vetur">Installing Vetur</h4>
<p>Clicking the Install button will trigger the installation panel in VS Code:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/hskNZD-byUAunDSOjCdPXPMIb9v3rBPSlOvf" alt="Image" width="800" height="630" loading="lazy"></p>
<p>You can also simply open the Extensions in VS Code and search for “vetur”:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/xbOVISLaIuAgHHvD4gKVFb0Lg9R1f5R5Jowk" alt="Image" width="800" height="497" loading="lazy"></p>
<p>What does this extension provide?</p>
<h4 id="heading-syntax-highlighting">Syntax highlighting</h4>
<p>Vetur provides syntax highlighting for all your Vue source code files.</p>
<p>Without Vetur, a <code>.vue</code> file will be displayed in this way by VS Code:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/JTZ9KScP0WTtr-4cCvjvQJKkGwlA4EW9KIf3" alt="Image" width="800" height="599" loading="lazy"></p>
<p>with Vetur installed:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/c5wC-aTwknyXUSjqq9gbr-EqFbSDXSewix-N" alt="Image" width="800" height="565" loading="lazy"></p>
<p>VS Code is able to recognize the type of code contained in a file from its extension.</p>
<p>Using Single File Components, you can mix different types of code inside the same file, from CSS to JavaScript to HTML.</p>
<p>VS Code by default cannot recognize this kind of situation, and Vetur provides syntax highlighting for each kind of code you use.</p>
<p>Vetur enables support, among other things, for:</p>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
<li>Pug</li>
<li>Haml</li>
<li>SCSS</li>
<li>PostCSS</li>
<li>Sass</li>
<li>Stylus</li>
<li>TypeScript</li>
</ul>
<h4 id="heading-snippets">Snippets</h4>
<p>As with syntax highlighting, since VS Code cannot determine the kind of code contained in a part of a <code>.vue</code> file, it cannot provide the snippets we all love. Snippets are pieces of code we can add to the file, provided by specialized plugins.</p>
<p>Vetur gives VS Code the ability to use your favorite snippets in Single File Components.</p>
<h4 id="heading-intellisense">IntelliSense</h4>
<p><a target="_blank" href="https://code.visualstudio.com/docs/editor/intellisense">IntelliSense</a> is also enabled by Vetur, for each different language, with autocomplete:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/3KtNeQR4W8HVg-JVT0kmu33sL79xlWIT0KtY" alt="Image" width="800" height="584" loading="lazy"></p>
<h4 id="heading-scaffolding">Scaffolding</h4>
<p>In addition to enabling custom snippets, Vetur provides its own set of snippets. Each one creates a specific tag (template, script, or style) with its own language:</p>
<ul>
<li><code>scaffold</code></li>
<li><code>template with html</code></li>
<li><code>template with pug</code></li>
<li><code>script with JavaScript</code></li>
<li><code>script with TypeScript</code></li>
<li><code>style with CSS</code></li>
<li><code>style with CSS (scoped)</code></li>
<li><code>style with scss</code></li>
<li><code>style with scss (scoped)</code></li>
<li><code>style with less</code></li>
<li><code>style with less (scoped)</code></li>
<li><code>style with sass</code></li>
<li><code>style with sass (scoped)</code></li>
<li><code>style with postcss</code></li>
<li><code>style with postcss (scoped)</code></li>
<li><code>style with stylus</code></li>
<li><code>style with stylus (scoped)</code></li>
</ul>
<p>If you type <code>scaffold</code>, you'll get a starter pack for a single-file component:</p>
<pre><code>&lt;template&gt;
</code></pre><pre><code>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
</code></pre><pre><code>}&lt;/script&gt;
</code></pre><pre><code>&lt;style&gt;
</code></pre><pre><code>&lt;/style&gt;
</code></pre><p>The others are specific and create a single block of code.</p>
<p><strong>Note:</strong> (scoped) in the above list means that it applies to the current component only.</p>
<h4 id="heading-emmet">Emmet</h4>
<p><a target="_blank" href="https://emmet.io/">Emmet</a>, the popular HTML/CSS abbreviations engine, is supported by default. You can type one of the Emmet abbreviations, and by pressing <code>tab</code> VS Code will automatically expand it to the HTML equivalent:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/R7Q4k9hsI0yzBe-xaVIMxdBMukjQWzzIw-FG" alt="Image" width="889" height="603" loading="lazy"></p>
<h4 id="heading-linting-and-error-checking">Linting and error checking</h4>
<p>Vetur integrates with ESLint through the <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint">VS Code ESLint plugin</a>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/j1mnYvPYhNPWM00V0lDdxCwb5ZidBzG0Djtn" alt="Image" width="800" height="551" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/5Z2hR9l8ARVe3uucCT4iPzTsDZRuEh0gZSs8" alt="Image" width="800" height="551" loading="lazy"></p>
<h4 id="heading-code-formatting">Code Formatting</h4>
<p>Vetur provides automatic support for code formatting to format the whole file upon save — in combination with the <code>"editor.formatOnSave"</code> VS Code setting.</p>
<p>You can choose to disable automatic formatting for some specific languages by setting the <code>vetur.format.defaultFormatter.XXXXX</code> to <code>none</code> in the VS Code settings. To change one of those settings, just start searching for the string, and override what you want in the user settings on the right panel.</p>
<p>Most of the languages supported use <a target="_blank" href="https://prettier.io/">Prettier</a> for automatic formatting, a tool that’s becoming an industry standard. It uses your Prettier configuration to determine your preferences.</p>
<h3 id="heading-introducing-vue-components">Introducing Vue Components</h3>
<p>Components are single, independent units of an interface. They can have their own state, markup, and style.</p>
<h4 id="heading-how-to-use-components">How to use components</h4>
<p>Vue components can be defined in four main ways. Let’s talk in code.</p>
<p>The first is:</p>
<pre><code><span class="hljs-keyword">new</span> Vue({  <span class="hljs-comment">/* options */</span>})
</code></pre><p>The second is:</p>
<pre><code>Vue.component(<span class="hljs-string">'component-name'</span>, {  <span class="hljs-comment">/* options */</span>})
</code></pre><p>The third is by using local components. These are components that are only accessible by a specific component, and not available elsewhere (great for encapsulation).</p>
<p>The fourth is in <code>.vue</code> files, also called Single File Components.</p>
<p>Let’s dive into the first 3 ways in detail.</p>
<p>Using <code>new Vue()</code> or <code>Vue.component()</code> is the standard way to use Vue when you're building an application that is not a Single Page Application (SPA). You use this method, rather, when you’re just using Vue.js in some pages, like in a contact form or in the shopping cart. Or maybe Vue is used in all pages, but the server is rendering the layout, and you serve the HTML to the client, which then loads the Vue application you build.</p>
<p>In an SPA, where it’s Vue that builds the HTML, it’s more common to use Single File Components as they are more convenient.</p>
<p>You instantiate Vue by mounting it on a DOM element. If you have a <code>&lt;div id="app"&gt;</code> tag, you will use:</p>
<pre><code><span class="hljs-keyword">new</span> Vue({ <span class="hljs-attr">el</span>: <span class="hljs-string">'#app'</span> })
</code></pre><p>A component initialized with <code>new Vue</code> has no corresponding tag name, so it's usually the main container component.</p>
<p>Other components used in the application are initialized using <code>Vue.component()</code>. Such a component allows you to define a tag — with which you can embed the component multiple times in the application — and specify the output of the component in the <code>template</code> property:</p>
<pre><code>&lt;div id=<span class="hljs-string">"app"</span>&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">user-name</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Flavio"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">user-name</span>&gt;</span></span>&lt;/div&gt;
</code></pre><pre><code>Vue.component(<span class="hljs-string">'user-name'</span>, {  <span class="hljs-attr">props</span>: [<span class="hljs-string">'name'</span>],  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;p&gt;Hi {{ name }}&lt;/p&gt;'</span>})
</code></pre><pre><code><span class="hljs-keyword">new</span> Vue({  <span class="hljs-attr">el</span>: <span class="hljs-string">'#app'</span>})
</code></pre><p><a target="_blank" href="https://jsfiddle.net/flaviocopes/nvgedhq4/">See on JSFiddle</a></p>
<p>What are we doing? We are initializing a Vue root component on <code>#app</code>, and inside that, we use the Vue component <code>user-name</code>, which abstracts our greeting to the user.</p>
<p>The component accepts a prop, which is an attribute we use to pass data down to child components.</p>
<p>In the <code>Vue.component()</code> call we passed <code>user-name</code> as the first parameter. This gives the component a name. You can write the name in 2 ways here. The first is the one we used, called kebab-case. The second is called PascalCase, which is like camelCase, but with the first letter capitalized:</p>
<pre><code>Vue.component(<span class="hljs-string">'UserName'</span>, {  <span class="hljs-comment">/* ... */</span>})
</code></pre><p>Vue automatically creates an alias internally from <code>user-name</code> to <code>UserName</code>, and vice versa, so you can use whatever you like. It's generally best to use <code>UserName</code> in the JavaScript, and <code>user-name</code> in the template.</p>
<h4 id="heading-local-components">Local components</h4>
<p>Any component created using <code>Vue.component()</code> is globally registered. You don't need to assign it to a variable or pass it around to reuse it in your templates.</p>
<p>You can encapsulate components locally by assigning an object that defines the component object to a variable:</p>
<pre><code><span class="hljs-keyword">const</span> Sidebar = {  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;aside&gt;Sidebar&lt;/aside&gt;'</span>}
</code></pre><p>and then make it available inside another component by using the <code>components</code> property:</p>
<pre><code><span class="hljs-keyword">new</span> Vue({  <span class="hljs-attr">el</span>: <span class="hljs-string">'#app'</span>,  <span class="hljs-attr">components</span>: {    Sidebar  }})
</code></pre><p>You can write the component in the same file, but a great way to do this is to use JavaScript modules:</p>
<pre><code><span class="hljs-keyword">import</span> Sidebar <span class="hljs-keyword">from</span> <span class="hljs-string">'./Sidebar'</span>
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">el</span>: <span class="hljs-string">'#app'</span>,  <span class="hljs-attr">components</span>: {    Sidebar  }}
</code></pre><h4 id="heading-reusing-a-component">Reusing a component</h4>
<p>A child component can be added multiple times. Each separate instance is independent of the others:</p>
<pre><code>&lt;div id=<span class="hljs-string">"app"</span>&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">user-name</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Flavio"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">user-name</span>&gt;</span></span>  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">user-name</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Roger"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">user-name</span>&gt;</span></span>  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">user-name</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Syd"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">user-name</span>&gt;</span></span>&lt;/div&gt;
</code></pre><pre><code>Vue.component(<span class="hljs-string">'user-name'</span>, {  <span class="hljs-attr">props</span>: [<span class="hljs-string">'name'</span>],  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;p&gt;Hi {{ name }}&lt;/p&gt;'</span>})
</code></pre><pre><code><span class="hljs-keyword">new</span> Vue({  <span class="hljs-attr">el</span>: <span class="hljs-string">'#app'</span>})
</code></pre><p><a target="_blank" href="https://jsfiddle.net/flaviocopes/3kebv908/">See on JSFiddle</a></p>
<h4 id="heading-the-building-blocks-of-a-component">The building blocks of a component</h4>
<p>So far we’ve seen how a component can accept the <code>el</code>, <code>props</code> and <code>template</code> properties.</p>
<ul>
<li><code>el</code> is only used in root components initialized using <code>new Vue({})</code>, and identifies the DOM element the component will mount on.</li>
<li><code>props</code> lists all the properties that we can pass down to a child component</li>
<li><code>template</code> is where we can set up the component template, which will be responsible for defining the output the component generates.</li>
</ul>
<p>A component accepts other properties:</p>
<ul>
<li><code>data</code> the component local state</li>
<li><code>methods</code>: the component methods</li>
<li><code>computed</code>: the computed properties associated with the component</li>
<li><code>watch</code>: the component watchers</li>
</ul>
<h3 id="heading-single-file-components">Single File Components</h3>
<p>A Vue component can be declared in a JavaScript file (<code>.js</code>) like this:</p>
<pre><code>Vue.component(<span class="hljs-string">'component-name'</span>, {  <span class="hljs-comment">/* options */</span>})
</code></pre><p>or also:</p>
<pre><code><span class="hljs-keyword">new</span> Vue({  <span class="hljs-comment">/* options */</span>})
</code></pre><p>or it can be specified in a <code>.vue</code> file.</p>
<p>The <code>.vue</code> file is pretty cool because it allows you to define:</p>
<ul>
<li>JavaScript logic</li>
<li>HTML code template</li>
<li>CSS styling</li>
</ul>
<p>all in just a single file. As such it got the name of Single File Component.</p>
<p>Here’s an example:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{{ hello }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">hello</span>: <span class="hljs-string">'Hello World!'</span>    }  }}&lt;/script&gt;
</code></pre><pre><code>&lt;style scoped&gt;  p {    <span class="hljs-attr">color</span>: blue;  }&lt;/style&gt;
</code></pre><p>All of this is possible thanks to the use of Webpack. The Vue CLI makes this very easy and supported out of the box. <code>.vue</code>files cannot be used without a Webpack setup, and as such, they are not very suited to apps that just use Vue on a page without being a full-blown single-page app (SPA).</p>
<p>Since Single File Components rely on Webpack, we get for free the ability to use modern Web features.</p>
<p>Your CSS can be defined using SCSS or Stylus, the template can be built using Pug, and all you need to do to make this happen is to declare to Vue which language preprocessor you are going to use.</p>
<p>The list of supported preprocessors include</p>
<ul>
<li>TypeScript</li>
<li>SCSS</li>
<li>Sass</li>
<li>Less</li>
<li>PostCSS</li>
<li>Pug</li>
</ul>
<p>We can use modern JavaScript (ES6–7–8) regardless of the target browser using the Babel integration, and ES Modules too, so we can use <code>import/export</code> statements.</p>
<p>We can use CSS Modules to scope our CSS.</p>
<p>Speaking of scoping CSS, Single File Components make it absolutely easy to write CSS that won’t <strong>leak</strong> to other components, by using <code>&lt;style scop</code>ed&gt; tags.</p>
<p>If you omit <code>scoped</code>, the CSS you define will be global. But adding the <code>scoped</code> tag, Vue automatically adds a specific class to the component, unique to your app, so the CSS is guaranteed to not leak out to other components.</p>
<p>Maybe your JavaScript is huge because of some logic you need to take care of. What if you want to use a separate file for your JavaScript?</p>
<p>You can use the <code>src</code> attribute to externalize it:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{{ hello }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;<span class="hljs-regexp">/template&gt;&lt;script src="./</span>hello.js<span class="hljs-string">"&gt;&lt;/script&gt;</span>
</code></pre><p>This also works for your CSS:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{{ hello }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;<span class="hljs-regexp">/template&gt;&lt;script src="./</span>hello.js<span class="hljs-string">"&gt;&lt;/script&gt;&lt;style src="</span>./hello.css<span class="hljs-string">"&gt;&lt;/style&gt;</span>
</code></pre><p>Notice how I used</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">hello</span>: <span class="hljs-string">'Hello World!'</span>    }  }}
</code></pre><p>in the component’s JavaScript to set up the data.</p>
<p>Other common ways you will see are:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">data</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">name</span>: <span class="hljs-string">'Flavio'</span>    }  }}
</code></pre><p>The above is equivalent to what we did before.</p>
<p>Or:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">data</span>: <span class="hljs-function">() =&gt;</span> {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">name</span>: <span class="hljs-string">'Flavio'</span>    }  }}
</code></pre><p>This is different, because it uses an arrow function. Arrow functions are fine until we need to access a component method. This is an issue if we need to make use of <code>this</code>, and such property is not bound to the component using arrow functions. So it's mandatory to use <strong>regular</strong> functions rather than arrow functions.</p>
<p>You might also see:</p>
<pre><code><span class="hljs-built_in">module</span>.exports = {  <span class="hljs-attr">data</span>: <span class="hljs-function">() =&gt;</span> {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">name</span>: <span class="hljs-string">'Flavio'</span>    }  }}
</code></pre><p>This is using the <a target="_blank" href="http://requirejs.org/docs/commonjs.html">CommonJS</a> syntax and it works as well. But I recommend using the ES Modules syntax, as that is a JavaScript standard.</p>
<h3 id="heading-vue-templates">Vue Templates</h3>
<p>Vue.js uses a templating language that’s a superset of HTML.</p>
<p>Any HTML is a valid Vue.js template. In addition to that, Vue.js provides two powerful things: interpolation and directives.</p>
<p>This is a valid Vue.js template:</p>
<pre><code>&lt;span&gt;Hello!&lt;/span&gt;
</code></pre><p>This template can be put inside a Vue component declared explicitly:</p>
<pre><code><span class="hljs-keyword">new</span> Vue({  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;span&gt;Hello!&lt;/span&gt;'</span>})
</code></pre><p>or it can be put into a Single File Component:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Hello!<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>&lt;/template&gt;
</code></pre><p>This first example is very basic. The next step is making it output a piece of the component state, for example, a name.</p>
<p>This can be done using interpolation. First, we add some data to our component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">new</span> Vue({  
  <span class="hljs-attr">data</span>: {    
    <span class="hljs-attr">name</span>: <span class="hljs-string">'Flavio'</span>  
  },  
  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;span&gt;Hello!&lt;/span&gt;'</span>
})
</code></pre>
<p>and then we can add it to our template using the double brackets syntax:</p>
<pre><code><span class="hljs-keyword">new</span> Vue({  <span class="hljs-attr">data</span>: {    <span class="hljs-attr">name</span>: <span class="hljs-string">'Flavio'</span>  },  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;span&gt;Hello {{name}}!&lt;/span&gt;'</span>})
</code></pre><p>One interesting thing here. See how we just used <code>name</code> instead of <code>this.data.name</code>?</p>
<p>This is because Vue.js does some internal binding and lets the template use the property as if it was local. Pretty handy.</p>
<p>In a single file component, that would be:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Hello {{name}}!<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">name</span>: <span class="hljs-string">'Flavio'</span>    }  }}&lt;/script&gt;
</code></pre><p>I used a regular function in my export. Why not an arrow function?</p>
<p>This is because in <code>data</code> we might need to access a method in our component instance, and we can't do that if <code>this</code> is not bound to the component, so we can’t use an arrow function.</p>
<p>Do note that we could use an arrow function, but then I would need to remember to switch to a regular function in case I use <code>this</code>. Better play it safe, I think.</p>
<p>Now, back to the interpolation.</p>
<p><code>{{ name }}</code> should remind you of Mustache / Handlebars template interpolation, but it's just a visual reminder.</p>
<p>While in those templating engines they are “dumb”, in Vue, you can do much more, and it’s more flexible.</p>
<p>You can use any JavaScript expression inside your interpolations, but you’re limited to just one expression:</p>
<pre><code>{{ name.reverse() }}
</code></pre><pre><code>{{ name === <span class="hljs-string">'Flavio'</span> ? <span class="hljs-string">'Flavio'</span> : <span class="hljs-string">'stranger'</span> }}
</code></pre><p>Vue provides access to some global objects inside templates, including Math and Date, so you can use them:</p>
<pre><code>{{ <span class="hljs-built_in">Math</span>.sqrt(<span class="hljs-number">16</span>) * <span class="hljs-built_in">Math</span>.random() }}
</code></pre><p>It’s best to avoid adding complex logic to templates, but the fact that Vue allows it gives us more flexibility, especially when trying things out.</p>
<p>We can first try to put an expression in the template, and then move it to a computed property or method later on.</p>
<p>The value included in any interpolation will be updated upon a change of any of the data properties it relies on.</p>
<p>You can avoid this reactivity by using the <code>v-once</code> directive.</p>
<p>The result is always escaped, so you can’t have HTML in the output.</p>
<p>If you need to have an HTML snippet, you need to use the <code>v-html</code> directive instead.</p>
<h3 id="heading-styling-components-using-css">Styling components using CSS</h3>
<p>The simplest option to add CSS to a Vue.js component is to use the <code>style</code> tag, just like in HTML:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"text-decoration: underline"</span>&gt;</span>Hi!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">decoration</span>: <span class="hljs-string">'underline'</span>    }  }}&lt;/script&gt;
</code></pre><p>This is as static as you can get. What if you want <code>underline</code> to be defined in the component data? Here's how you can do it:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">:style</span>=<span class="hljs-string">"{'text-decoration': decoration}"</span>&gt;</span>Hi!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">decoration</span>: <span class="hljs-string">'underline'</span>    }  }}&lt;/script&gt;
</code></pre><p><code>:style</code> is a shorthand for <code>v-bind:style</code>. I'll use this shorthand throughout this tutorial.</p>
<p>Notice how we had to wrap <code>text-decoration</code> in quotes. This is because of the dash, which is not part of a valid JavaScript identifier.</p>
<p>You can avoid the quotes by using a special camelCase syntax that Vue.js enables, and rewriting it to <code>textDecoration</code>:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">:style</span>=<span class="hljs-string">"{textDecoration: decoration}"</span>&gt;</span>Hi!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><p>Instead of binding an object to <code>style</code>, you can reference a computed property:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">:style</span>=<span class="hljs-string">"styling"</span>&gt;</span>Hi!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">textDecoration</span>: <span class="hljs-string">'underline'</span>,      <span class="hljs-attr">textWeight</span>: <span class="hljs-string">'bold'</span>    }  },  <span class="hljs-attr">computed</span>: {    <span class="hljs-attr">styling</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      <span class="hljs-keyword">return</span> {        <span class="hljs-attr">textDecoration</span>: <span class="hljs-built_in">this</span>.textDecoration,        <span class="hljs-attr">textWeight</span>: <span class="hljs-built_in">this</span>.textWeight      }    }  }}&lt;/script&gt;
</code></pre><p>Vue components generate plain HTML, so you can choose to add a class to each element, and add a corresponding CSS selector with properties that style it:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"underline"</span>&gt;</span>Hi!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;style&gt;.underline { text-decoration: underline; }&lt;/style&gt;
</code></pre><p>You can use SCSS like this:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"underline"</span>&gt;</span>Hi!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;style lang=<span class="hljs-string">"scss"</span>&gt;body {  .underline { text-decoration: underline; }}&lt;/style&gt;
</code></pre><p>You can hard code the class like in the above example. Or you can bind the class to a component property, to make it dynamic, and only apply to that class if the data property is true:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">:class</span>=<span class="hljs-string">"{underline: isUnderlined}"</span>&gt;</span>Hi!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">isUnderlined</span>: <span class="hljs-literal">true</span>    }  }}&lt;/script&gt;
</code></pre><pre><code>&lt;style&gt;.underline { text-decoration: underline; }&lt;/style&gt;
</code></pre><p>Instead of binding an object to class, like we did with <code>&lt;p :class="{text: isText}"&gt;H</code>i!</p>, you can directly bind a string, and that will reference a data property:<p></p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">:class</span>=<span class="hljs-string">"paragraphClass"</span>&gt;</span>Hi!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">paragraphClass</span>: <span class="hljs-string">'underline'</span>    }  }}&lt;/script&gt;
</code></pre><pre><code>&lt;style&gt;.underline { text-decoration: underline; }&lt;/style&gt;
</code></pre><p>You can assign multiple classes, either by adding two classes to <code>paragraphClass</code> in this case or by using an array:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">:class</span>=<span class="hljs-string">"[decoration, weight]"</span>&gt;</span>Hi!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">decoration</span>: <span class="hljs-string">'underline'</span>,      <span class="hljs-attr">weight</span>: <span class="hljs-string">'weight'</span>,    }  }}&lt;/script&gt;
</code></pre><pre><code>&lt;style&gt;.underline { text-decoration: underline; }.weight { font-weight: bold; }&lt;/style&gt;
</code></pre><p>The same can be done using an object inlined in the class binding:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">:class</span>=<span class="hljs-string">"{underline: isUnderlined, weight: isBold}"</span>&gt;</span>Hi!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">isUnderlined</span>: <span class="hljs-literal">true</span>,      <span class="hljs-attr">isBold</span>: <span class="hljs-literal">true</span>    }  }}&lt;/script&gt;
</code></pre><pre><code>&lt;style&gt;.underline { text-decoration: underline; }.weight { font-weight: bold; }&lt;/style&gt;
</code></pre><p>And you can combine the two statements:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">:class</span>=<span class="hljs-string">"[decoration, {weight: isBold}]"</span>&gt;</span>Hi!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">decoration</span>: <span class="hljs-string">'underline'</span>,      <span class="hljs-attr">isBold</span>: <span class="hljs-literal">true</span>    }  }}&lt;/script&gt;
</code></pre><pre><code>&lt;style&gt;.underline { text-decoration: underline; }.weight { font-weight: bold; }&lt;/style&gt;
</code></pre><p>You can also use a computed property that returns an object, which works best when you have many CSS classes to add to the same element:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">:class</span>=<span class="hljs-string">"paragraphClasses"</span>&gt;</span>Hi!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">isUnderlined</span>: <span class="hljs-literal">true</span>,      <span class="hljs-attr">isBold</span>: <span class="hljs-literal">true</span>    }  },  <span class="hljs-attr">computed</span>: {    <span class="hljs-attr">paragraphClasses</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      <span class="hljs-keyword">return</span> {        <span class="hljs-attr">underlined</span>: <span class="hljs-built_in">this</span>.isUnderlined,        <span class="hljs-attr">bold</span>: <span class="hljs-built_in">this</span>.isBold      }    }  }}&lt;/script&gt;
</code></pre><pre><code>&lt;style&gt;.underlined { text-decoration: underline; }.bold { font-weight: bold; }&lt;/style&gt;
</code></pre><p>Notice that in the computed property you need to reference the component data using <code>this.[propertyName]</code>, while in the template data, properties are conveniently put as first-level properties.</p>
<p>Any CSS that’s not hard coded like in the first example is going to be processed by Vue, and Vue does the nice job of automatically prefixing the CSS for us. This allows us to write clean CSS while still targeting older browsers (which still means browsers that Vue supports, so IE9+).</p>
<h3 id="heading-directives">Directives</h3>
<p>We saw in Vue.js templates and interpolations how you can embed data in Vue templates.</p>
<p>This section explains the other technique offered by Vue.js in templates: directives.</p>
<p>Directives are basically like HTML attributes which are added inside templates. They all start with <code>v-</code>, to indicate that's a Vue special attribute.</p>
<p>Let’s see each of the Vue directives in detail.</p>
<h4 id="heading-v-text"><code>v-text</code></h4>
<p>Instead of using interpolation, you can use the <code>v-text</code> directive. It performs the same job:</p>
<pre><code>&lt;span v-text=<span class="hljs-string">"name"</span>&gt;&lt;/span&gt;
</code></pre><h4 id="heading-v-once"><code>v-once</code></h4>
<p>You know how <code>{{ name }}</code> binds to the <code>name</code> property of the component data.</p>
<p>Any time <code>name</code> changes in your component data, Vue is going to update the value represented in the browser.</p>
<p>Unless you use the <code>v-once</code> directive, which is basically like an HTML attribute:</p>
<pre><code>&lt;span v-once&gt;{{ name }}&lt;/span&gt;
</code></pre><h4 id="heading-v-html"><code>v-html</code></h4>
<p>When you use interpolation to print a data property, the HTML is escaped. This is a great way that Vue uses to automatically protect from XSS attacks.</p>
<p>There are cases, however, where you want to output HTML and make the browser interpret it. You can use the <code>v-html</code>directive:</p>
<pre><code>&lt;span v-html=<span class="hljs-string">"someHtml"</span>&gt;&lt;/span&gt;
</code></pre><h4 id="heading-v-bind"><code>v-bind</code></h4>
<p>Interpolation only works in the tag content. You can’t use it on attributes.</p>
<p>Attributes must use <code>v-bind</code>:</p>
<pre><code>&lt;a v-bind:href=<span class="hljs-string">"url"</span>&gt;{{ linkText }}&lt;/a&gt;
</code></pre><p><code>v-bind</code> is so common that there is a shorthand syntax for it:</p>
<pre><code>&lt;a v-bind:href=<span class="hljs-string">"url"</span>&gt;{{ linkText }}&lt;<span class="hljs-regexp">/a&gt;&lt;a :href="url"&gt;{{ linkText }}&lt;/</span>a&gt;
</code></pre><h4 id="heading-two-way-binding-using-v-model">Two-way binding using <code>v-model</code></h4>
<p><code>v-model</code> lets us bind a form input element for example, and makes it change the Vue data property when the user changes the content of the field:</p>
<pre><code>&lt;input v-model=<span class="hljs-string">"message"</span> placeholder=<span class="hljs-string">"Enter a message"</span>&gt;<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Message is: {{ message }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
</code></pre><pre><code>&lt;select v-model=<span class="hljs-string">"selected"</span>&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">disabled</span> <span class="hljs-attr">value</span>=<span class="hljs-string">""</span>&gt;</span>Choose a fruit<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span></span>  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">option</span>&gt;</span>Apple<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span></span>  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">option</span>&gt;</span>Banana<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span></span>  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">option</span>&gt;</span>Strawberry<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span></span>&lt;<span class="hljs-regexp">/select&gt;&lt;span&gt;Fruit chosen: {{ selected }}&lt;/</span>span&gt;
</code></pre><h4 id="heading-using-expressions">Using expressions</h4>
<p>You can use any JavaScript expression inside a directive:</p>
<pre><code>&lt;span v-text=<span class="hljs-string">"'Hi, ' + name + '!'"</span>&gt;&lt;/span&gt;
</code></pre><pre><code>&lt;a v-bind:href=<span class="hljs-string">"'https://' + domain + path"</span>&gt;{{ linkText }}&lt;/a&gt;
</code></pre><p>Any variable used in a directive references the corresponding data property.</p>
<h4 id="heading-conditionals">Conditionals</h4>
<p>Inside a directive you can use the ternary operator to perform a conditional check, since that’s an expression:</p>
<pre><code>&lt;span v-text=<span class="hljs-string">"name == Flavio ? 'Hi Flavio!' : 'Hi' + name + '!'"</span>&gt;&lt;/span&gt;
</code></pre><p>There are dedicated directives that allow you to perform more organized conditionals: <code>v-if</code>, <code>v-else</code> and <code>v-else-if</code>.</p>
<pre><code>&lt;p v-<span class="hljs-keyword">if</span>=<span class="hljs-string">"shouldShowThis"</span>&gt;Hey!&lt;/p&gt;
</code></pre><p><code>shouldShowThis</code> is a boolean value contained in the component's data.</p>
<h4 id="heading-loops">Loops</h4>
<p><code>v-for</code> allows you to render a list of items. Use it in combination with <code>v-bind</code> to set the properties of each item in the list.</p>
<p>You can iterate on a simple array of values:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"item in items"</span>&gt;</span>{{ item }}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">items</span>: [<span class="hljs-string">'car'</span>, <span class="hljs-string">'bike'</span>, <span class="hljs-string">'dog'</span>]    }  }}&lt;/script&gt;
</code></pre><p>Or on an array of objects:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>    <span class="hljs-comment">&lt;!-- using interpolation --&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>      <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"todo in todos"</span>&gt;</span>{{ todo.title }}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>    <span class="hljs-comment">&lt;!-- using v-text --&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>      <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"todo in todos"</span> <span class="hljs-attr">v-text</span>=<span class="hljs-string">"todo.title"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">todos</span>: [        { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'Do something'</span> },        { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'Do something else'</span> }      ]    }  }}&lt;/script&gt;
</code></pre><p><code>v-for</code> can give you the index using:</p>
<pre><code>&lt;li v-<span class="hljs-keyword">for</span>=<span class="hljs-string">"(todo, index) in todos"</span>&gt;&lt;/li&gt;
</code></pre><h4 id="heading-events">Events</h4>
<p><code>v-on</code> allows you to listen to DOM events, and trigger a method when the event happens. Here we listen for a click event:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">v-on:click</span>=<span class="hljs-string">"handleClick"</span>&gt;</span>Click me!<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClick</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      alert(<span class="hljs-string">'test'</span>)    }  }}&lt;/script&gt;
</code></pre><p>You can pass parameters to any event:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">v-on:click</span>=<span class="hljs-string">"handleClick('test')"</span>&gt;</span>Click me!<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClick</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{      alert(value)    }  }}&lt;/script&gt;
</code></pre><p>Small bits of JavaScript (a single expression) can be put directly into the template:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">v-on:click</span>=<span class="hljs-string">"counter = counter + 1"</span>&gt;</span>{{counter}}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">data</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">counter</span>: <span class="hljs-number">0</span>    }  }}&lt;/script&gt;
</code></pre><p><code>click</code> is just one kind of event. A common event is <code>submit</code>, which you can bind using <code>v-on:submit</code>.</p>
<p><code>v-on</code> is so common that there is a shorthand syntax for it, <code>@</code>:</p>
<pre><code>&lt;a v-on:click=<span class="hljs-string">"handleClick"</span>&gt;Click me!&lt;<span class="hljs-regexp">/a&gt;&lt;a @click="handleClick"&gt;Click me!&lt;/</span>a&gt;
</code></pre><h4 id="heading-show-or-hide">Show or hide</h4>
<p>You can choose to only show an element in the DOM if a particular property of the Vue instance evaluates to true, using <code>v-show</code>:</p>
<pre><code>&lt;p v-show=<span class="hljs-string">"isTrue"</span>&gt;Something&lt;/p&gt;
</code></pre><p>The element is still inserted in the DOM, but set to <code>display: none</code> if the condition is not satisfied.</p>
<h4 id="heading-event-directive-modifiers">Event directive modifiers</h4>
<p>Vue offers some optional event modifiers you can use in association with <code>v-on</code>, which automatically make the event do something without you explicitly coding it in your event handler.</p>
<p>One good example is <code>.prevent</code>, which automatically calls <code>preventDefault()</code> on the event.</p>
<p>In this case, the form does not cause the page to be reloaded, which is the default behavior:</p>
<pre><code>&lt;form v-on:submit.prevent=<span class="hljs-string">"formSubmitted"</span>&gt;&lt;/form&gt;
</code></pre><p>Other modifiers include <code>.stop</code>, <code>.capture</code>, <code>.self</code>, <code>.once</code>, <code>.passive</code> and they are <a target="_blank" href="https://vuejs.org/v2/guide/events.html#Event-Modifiers">described in detail in the official docs</a>.</p>
<h4 id="heading-custom-directives">Custom directives</h4>
<p>The Vue default directives already let you do a lot of work, but you can always add new, custom directives if you want.</p>
<p>Read <a target="_blank" href="https://vuejs.org/v2/guide/custom-directive.html">here</a> if you’re interested in learning more.</p>
<h3 id="heading-methods">Methods</h3>
<h4 id="heading-what-are-vuejs-methods">What are Vue.js methods?</h4>
<p>A Vue method is a function associated with the Vue instance.</p>
<p>Methods are defined inside the <code>methods</code> property:</p>
<pre><code><span class="hljs-keyword">new</span> Vue({  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClick</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      alert(<span class="hljs-string">'test'</span>)    }  }})
</code></pre><p>or in the case of Single File Components:</p>
<pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClick</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      alert(<span class="hljs-string">'test'</span>)    }  }}&lt;/script&gt;
</code></pre><p>Methods are especially useful when you need to perform an action and you attach a <code>v-on</code> directive on an element to handle events. Like this one, which calls <code>handleClick</code> when the element is clicked:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"handleClick"</span>&gt;</span>Click me!<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>&lt;/template&gt;
</code></pre><h4 id="heading-pass-parameters-to-vuejs-methods">Pass parameters to Vue.js methods</h4>
<p>Methods can accept parameters.</p>
<p>In this case, you just pass the parameter in the template:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"handleClick('something')"</span>&gt;</span>Click me!<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code><span class="hljs-keyword">new</span> Vue({  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClick</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">text</span>) </span>{      alert(text)    }  }})
</code></pre><p>or in the case of Single File Components:</p>
<pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClick</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">text</span>) </span>{      alert(text)    }  }}&lt;/script&gt;
</code></pre><h4 id="heading-how-to-access-data-from-a-method">How to access data from a method</h4>
<p>You can access any of the data properties of the Vue component by using <code>this.propertyName</code>:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"handleClick()"</span>&gt;</span>Click me!<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">name</span>: <span class="hljs-string">'Flavio'</span>    }  },  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClick</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">this</span>.name)    }  }}&lt;/script&gt;
</code></pre><p>We don’t have to use <code>this.data.name</code>, just <code>this.name</code>. Vue does provide a transparent binding for us. Using <code>this.data.name</code> will raise an error.</p>
<p>As you saw before in the <strong>events</strong> description, methods are closely interlinked to events, because they are used as event handlers. Every time an event occurs, that method is called.</p>
<h3 id="heading-watchers">Watchers</h3>
<p>A watcher is a special Vue.js feature that allows you to spy on one property of the component state, and run a function when that property value changes.</p>
<p>Here’s an example. We have a component that shows a name, and allows you to change it by clicking a button:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>My name is {{name}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"changeName()"</span>&gt;</span>Change my name!<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">name</span>: <span class="hljs-string">'Flavio'</span>    }  },  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">changeName</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      <span class="hljs-built_in">this</span>.name = <span class="hljs-string">'Flavius'</span>    }  }}&lt;/script&gt;
</code></pre><p>When the name changes we want to do something, like print a console log.</p>
<p>We can do so by adding to the <code>watch</code> object a property named as the data property we want to watch over:</p>
<pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">name</span>: <span class="hljs-string">'Flavio'</span>    }  },  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">changeName</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      <span class="hljs-built_in">this</span>.name = <span class="hljs-string">'Flavius'</span>    }  },  <span class="hljs-attr">watch</span>: {    <span class="hljs-attr">name</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">this</span>.name)    }  }}&lt;/script&gt;
</code></pre><p>The function assigned to <code>watch.name</code> can optionally accept 2 parameters. The first is the new property value. The second is the old property value:</p>
<pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-comment">/* ... */</span>  watch: {    <span class="hljs-attr">name</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">newValue, oldValue</span>) </span>{      <span class="hljs-built_in">console</span>.log(newValue, oldValue)    }  }}&lt;/script&gt;
</code></pre><p>Watchers cannot be looked up from a template as you can with computed properties.</p>
<h3 id="heading-computed-properties">Computed Properties</h3>
<h4 id="heading-what-is-a-computed-property">What is a Computed Property</h4>
<p>In Vue.js you can output any data value using parentheses:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{{ count }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">count</span>: <span class="hljs-number">1</span>    }  }}&lt;/script&gt;
</code></pre><p>This property can host some small computations. For example:</p>
<pre><code>&lt;template&gt;  {{ count * <span class="hljs-number">10</span> }}&lt;/template&gt;
</code></pre><p>But you’re limited to a single JavaScript <strong>expression</strong>.</p>
<p>In addition to this technical limitation, you also need to consider that templates should only be concerned with displaying data to the user, not perform logic computations.</p>
<p>To do something more than a single expression, and to have more declarative templates, you use a computed property.</p>
<p>Computed properties are defined in the <code>computed</code> property of the Vue component:</p>
<pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">computed</span>: {
</code></pre><pre><code>  }}&lt;/script&gt;
</code></pre><h4 id="heading-an-example-of-a-computed-property">An example of a computed property</h4>
<p>Here’s an example that uses a computed property <code>count</code> to calculate the output.</p>
<p>Notice:</p>
<ol>
<li>I didn’t have to call <code>{{ count() }}</code>. Vue.js automatically invokes the function</li>
<li>I used a regular function (not an arrow function) to define the <code>count</code> computed property, because I need to be able to access the component instance through <code>this</code>.</li>
</ol>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{{ count }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">items</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]    }  },  <span class="hljs-attr">computed</span>: {    <span class="hljs-attr">count</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      <span class="hljs-keyword">return</span> <span class="hljs-string">'The count is '</span> + <span class="hljs-built_in">this</span>.items.length * <span class="hljs-number">10</span>    }  }}&lt;/script&gt;
</code></pre><h4 id="heading-computed-properties-vs-methods">Computed properties vs. methods</h4>
<p>If you already know about Vue methods, you may wonder what’s the difference.</p>
<p>First, methods must be called, not just referenced, so you’d need to do:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{{ count() }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">items</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]    }  },  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">count</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      <span class="hljs-keyword">return</span> <span class="hljs-string">'The count is '</span> + <span class="hljs-built_in">this</span>.items.length * <span class="hljs-number">10</span>    }  }}&lt;/script&gt;
</code></pre><p>But the main difference is that computed properties are cached.</p>
<p>The result of the <code>count</code> computed property is internally cached until the <code>items</code> data property changes.</p>
<p><strong>Important:</strong> Computed properties are only updated when a reactive source updates. Regular JavaScript methods are not reactive, so a common example is to use <code>Date.now()</code>:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{{ now }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">computed</span>: {    <span class="hljs-attr">now</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{      <span class="hljs-keyword">return</span> <span class="hljs-built_in">Date</span>.now()    }  }}&lt;/script&gt;
</code></pre><p>It will render once, and then it will not be updated even when the component re-renders. It’s just updated on a page refresh, when the Vue component is quit and reinitialized.</p>
<p>In this case, a method is better suited for your needs.</p>
<h3 id="heading-methods-vs-watchers-vs-computed-properties">Methods vs. Watchers vs. Computed Properties</h3>
<p>Now that you know about methods, watchers and computed properties, you might be wondering when should you use one vs the others.</p>
<p>Here’s a breakdown of this question.</p>
<h4 id="heading-when-to-use-methods">When to use methods</h4>
<ul>
<li>To react to some event happening in the DOM</li>
<li>To call a function when something happens in your component.<br>You can call a method from computed properties or watchers.</li>
</ul>
<h4 id="heading-when-to-use-computed-properties">When to use computed properties</h4>
<ul>
<li>You need to compose new data from existing data sources</li>
<li>You have a variable you use in your template that’s built from one or more data properties</li>
<li>You want to reduce a complicated, nested property name to a more readable and easy to use one (but update it when the original property changes)</li>
<li>You need to reference a value from the template. In this case, creating a computed property is the best thing, because it’s cached.</li>
<li>You need to listen to changes of more than one data property</li>
</ul>
<h4 id="heading-when-to-use-watchers">When to use watchers</h4>
<ul>
<li>You want to listen when a data property changes, and perform some action</li>
<li>You want to listen to a prop value change</li>
<li>You only need to listen to one specific property (you can’t watch multiple properties at the same time)</li>
<li>You want to watch a data property until it reaches some specific value and then do something</li>
</ul>
<h3 id="heading-props-pass-data-to-child-components">Props: pass data to child components</h3>
<p>Props are the way components can accept data from components that include them (parent components).</p>
<p>When a component expects one or more prop, it must define them in its <code>props</code> property:</p>
<pre><code>Vue.component(<span class="hljs-string">'user-name'</span>, {  <span class="hljs-attr">props</span>: [<span class="hljs-string">'name'</span>],  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;p&gt;Hi {{ name }}&lt;/p&gt;'</span>})
</code></pre><p>or, in a Vue Single File Component:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{{ name }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">props</span>: [<span class="hljs-string">'name'</span>]}&lt;/script&gt;
</code></pre><h4 id="heading-accept-multiple-props">Accept multiple props</h4>
<p>You can have multiple props by simply appending them to the array:</p>
<pre><code>Vue.component(<span class="hljs-string">'user-name'</span>, {  <span class="hljs-attr">props</span>: [<span class="hljs-string">'firstName'</span>, <span class="hljs-string">'lastName'</span>],  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;p&gt;Hi {{ firstName }} {{ lastName }}&lt;/p&gt;'</span>})
</code></pre><h4 id="heading-set-the-prop-type">Set the prop type</h4>
<p>You can specify the type of a prop very simply by using an object instead of an array, using the name of the property as the key of each property, and the type as the value:</p>
<pre><code>Vue.component(<span class="hljs-string">'user-name'</span>, {  <span class="hljs-attr">props</span>: {    <span class="hljs-attr">firstName</span>: <span class="hljs-built_in">String</span>,    <span class="hljs-attr">lastName</span>: <span class="hljs-built_in">String</span>  },  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;p&gt;Hi {{ firstName }} {{ lastName }}&lt;/p&gt;'</span>})
</code></pre><p>The valid types you can use are:</p>
<ul>
<li>String</li>
<li>Number</li>
<li>Boolean</li>
<li>Array</li>
<li>Object</li>
<li>Date</li>
<li>Function</li>
<li>Symbol</li>
</ul>
<p>When a type mismatches, Vue alerts you (in development mode) in the console with a warning.</p>
<p>Prop types can be more articulated.</p>
<p>You can allow multiple different value types:</p>
<pre><code>props: {  <span class="hljs-attr">firstName</span>: [<span class="hljs-built_in">String</span>, <span class="hljs-built_in">Number</span>]}
</code></pre><h4 id="heading-set-a-prop-to-be-mandatory">Set a prop to be mandatory</h4>
<p>You can require a prop to be mandatory:</p>
<pre><code>props: {  <span class="hljs-attr">firstName</span>: {    <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,    <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>  }}
</code></pre><h4 id="heading-set-the-default-value-of-a-prop">Set the default value of a prop</h4>
<p>You can specify a default value:</p>
<pre><code>props: {  <span class="hljs-attr">firstName</span>: {    <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,    <span class="hljs-attr">default</span>: <span class="hljs-string">'Unknown person'</span>  }}
</code></pre><p>For objects:</p>
<pre><code>props: {  <span class="hljs-attr">name</span>: {    <span class="hljs-attr">type</span>: <span class="hljs-built_in">Object</span>,    <span class="hljs-attr">default</span>: {      <span class="hljs-attr">firstName</span>: <span class="hljs-string">'Unknown'</span>,      <span class="hljs-attr">lastName</span>: <span class="hljs-string">''</span>    }  }}
</code></pre><p><code>default</code> can also be a function that returns an appropriate value, rather than being the actual value.</p>
<p>You can even build a custom validator, which is cool for complex data:</p>
<pre><code>props: {  <span class="hljs-attr">name</span>: {    <span class="hljs-attr">validator</span>: <span class="hljs-function"><span class="hljs-params">name</span> =&gt;</span> {      <span class="hljs-keyword">return</span> name === <span class="hljs-string">'Flavio'</span> <span class="hljs-comment">//only allow "Flavios"    }  }}</span>
</code></pre><h4 id="heading-passing-props-to-the-component">Passing props to the component</h4>
<p>You pass a prop to a component using the syntax</p>
<pre><code>&lt;ComponentName color=<span class="hljs-string">"white"</span> /&gt;
</code></pre><p>if what you pass is a static value.</p>
<p>If it’s a data property, you use</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ComponentName</span> <span class="hljs-attr">:color</span>=<span class="hljs-string">color</span> /&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;...export <span class="hljs-keyword">default</span> {  <span class="hljs-comment">//...  data: function() {    return {      color: 'white'    }  },  //...}&lt;/script&gt;</span>
</code></pre><p>You can use a ternary operator inside the prop value to check a truthy condition and pass a value that depends on it:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ComponentName</span> <span class="hljs-attr">:colored</span>=<span class="hljs-string">"color == 'white' ? true : false"</span> /&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;...export <span class="hljs-keyword">default</span> {  <span class="hljs-comment">//...  data: function() {    return {      color: 'white'    }  },  //...}&lt;/script&gt;</span>
</code></pre><h3 id="heading-handling-events-in-vue">Handling Events in Vue</h3>
<h4 id="heading-what-are-vuejs-events">What are Vue.js events?</h4>
<p>Vue.js allows us to intercept any DOM event by using the <code>v-on</code> directive on an element.</p>
<p>If we want to do something when a click event happens in this element:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span>Click me!<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>&lt;/template&gt;
</code></pre><p>we add a <code>v-on</code> directive:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">v-on:click</span>=<span class="hljs-string">"handleClick"</span>&gt;</span>Click me!<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>&lt;/template&gt;
</code></pre><p>Vue also offers a very convenient alternative syntax for this:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"handleClick"</span>&gt;</span>Click me!<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>&lt;/template&gt;
</code></pre><p>You can choose to use the parentheses or not. <code>@click="handleClick"</code> is equivalent to <code>@click="handleClick()"</code>.</p>
<p><code>handleClick</code> is a method attached to the component:</p>
<pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClick</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>) </span>{      <span class="hljs-built_in">console</span>.log(event)    }  }}&lt;/script&gt;
</code></pre><p>What you need to know here is that you can pass parameters from events: <code>@click="handleClick(param)"</code> and they will be received inside the method.</p>
<h4 id="heading-access-the-original-event-object">Access the original event object</h4>
<p>In many cases, you will want to perform an action on the event object or look up some property in it. How can you access it?</p>
<p>Use the special <code>$event</code> directive:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"handleClick($event)"</span>&gt;</span>Click me!<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClick</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>) </span>{      <span class="hljs-built_in">console</span>.log(event)    }  }}&lt;/script&gt;
</code></pre><p>and if you already pass a variable:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"handleClick('something', $event)"</span>&gt;</span>Click me!<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClick</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">text, event</span>) </span>{      <span class="hljs-built_in">console</span>.log(text)      <span class="hljs-built_in">console</span>.log(event)    }  }}&lt;/script&gt;
</code></pre><p>From there you could call <code>event.preventDefault()</code>, but there's a better way: event modifiers.</p>
<h4 id="heading-event-modifiers">Event modifiers</h4>
<p>Instead of messing with DOM “things” in your methods, tell Vue to handle things for you:</p>
<ul>
<li><code>@click.prevent</code> call <code>event.preventDefault()</code></li>
<li><code>@click.stop</code> call <code>event.stopPropagation()</code></li>
<li><code>@click.passive</code> makes use of the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters">passive option of addEventListener</a></li>
<li><code>@click.capture</code> uses event capturing instead of event bubbling</li>
<li><code>@click.self</code> make sure the click event was not bubbled from a child event, but directly happened on that element</li>
<li><code>@click.once</code> the event will only be triggered exactly once</li>
</ul>
<p>All those options can be combined by appending one modifier after the other.</p>
<p>For more on propagation, bubbling and capturing, see my <a target="_blank" href="https://flaviocopes.com/javascript-events">JavaScript events guide</a>.</p>
<h3 id="heading-inject-content-using-slots">Inject content using slots</h3>
<p>A component can choose to define its content entirely, like in this case:</p>
<pre><code>Vue.component(<span class="hljs-string">'user-name'</span>, {  <span class="hljs-attr">props</span>: [<span class="hljs-string">'name'</span>],  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;p&gt;Hi {{ name }}&lt;/p&gt;'</span>})
</code></pre><p>Or it can also let the parent component inject any kind of content into it, by using slots.</p>
<p>What’s a slot?</p>
<p>You define it by putting <code>&lt;slot&gt;&amp;</code>lt;/slot&gt; in a component template:</p>
<pre><code>Vue.component(<span class="hljs-string">'user-information'</span>, {  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;div class="user-information"&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/div&gt;'</span>})
</code></pre><p>When using this component, any content added between the opening and closing tag will be added inside the slot placeholder:</p>
<pre><code>&lt;user-information&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Hi!<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">user-name</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Flavio"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">user-information</span>&gt;</span></span>
</code></pre><p>If you put any content side the <code>&lt;slot&gt;&amp;</code>lt;/slot&gt; tags, that serves as the default content in case nothing is passed in.</p>
<p>A complicated component layout might require a better way to organize content.</p>
<p>Enter <strong>named slots</strong>.</p>
<p>With a named slot, you can assign parts of a slot to a specific position in your component template layout, and you use a <code>slot</code> attribute to any tag, to assign content to that slot.</p>
<p>Anything outside any template tag is added to the main <code>slot</code>.</p>
<p>For convenience, I use a <code>page</code> single file component in this example:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>      <span class="hljs-tag">&lt;<span class="hljs-name">slot</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">slot</span>&gt;</span>    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">sidebar</span>&gt;</span>      <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"sidebar"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">slot</span>&gt;</span>    <span class="hljs-tag">&lt;/<span class="hljs-name">sidebar</span>&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;page&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"sidebar"</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Contact<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
</code></pre><pre><code>  &lt;h2&gt;Page title&lt;<span class="hljs-regexp">/h2&gt;  &lt;p&gt;Page content&lt;/</span>p&gt;&lt;/page&gt;
</code></pre><h3 id="heading-filters-helpers-for-templates">Filters, helpers for templates</h3>
<p>Filters are a functionality provided by Vue components that let you apply formatting and transformations to any part of your template dynamic data.</p>
<p>They don’t change a component’s data or anything, but they only affect the output.</p>
<p>Say you are printing a name:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hi {{ name }}!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">name</span>: <span class="hljs-string">'Flavio'</span>    }  }}&lt;/script&gt;
</code></pre><p>What if you want to check that <code>name</code> is actually containing a value, and if not print 'there', so that our template will print "Hi there!"?</p>
<p>Enter filters:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hi {{ name | fallback }}!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">name</span>: <span class="hljs-string">'Flavio'</span>    }  },  <span class="hljs-attr">filters</span>: {    <span class="hljs-attr">fallback</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">name</span>) </span>{      <span class="hljs-keyword">return</span> name ? name : <span class="hljs-string">'there'</span>    }  }}&lt;/script&gt;
</code></pre><p>Notice the syntax to apply a filter, which is <code>| filterName</code>. If you're familiar with Unix, that's the Unix pipe operator, which is used to pass the output of an operation as an input to the next one.</p>
<p>The <code>filters</code> property of the component is an object. A single filter is a function that accepts a value and returns another value.</p>
<p>The returned value is the one that’s actually printed in the Vue.js template.</p>
<p>The filter, of course, has access to the component data and methods.</p>
<p>What’s a good use case for filters?</p>
<ul>
<li>transforming a string, for example, capitalizing or making it lowercase</li>
<li>formatting a price</li>
</ul>
<p>Above you saw a simple example of a filter: <code>{{ name | fallback }}</code>.</p>
<p>Filters can be chained, by repeating the pipe syntax:</p>
<pre><code>{{ name | fallback | capitalize }}
</code></pre><p>This first applies the <code>fallback</code> filter, then the <code>capitalize</code> filter (which we didn't define, but try making one!).</p>
<p>Advanced filters can also accept parameters, using the normal function parameters syntax:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello {{ name | prepend('Dr.') }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  data() {    <span class="hljs-keyword">return</span> {      <span class="hljs-attr">name</span>: <span class="hljs-string">'House'</span>    }  },  <span class="hljs-attr">filters</span>: {    <span class="hljs-attr">prepend</span>: <span class="hljs-function">(<span class="hljs-params">name, prefix</span>) =&gt;</span> {      <span class="hljs-keyword">return</span> <span class="hljs-string">`<span class="hljs-subst">${prefix}</span> <span class="hljs-subst">${name}</span>`</span>    }  }}&lt;/script&gt;
</code></pre><p>If you pass parameters to a filter, the first one passed to the filter function is always the item in the template interpolation (<code>name</code> in this case), followed by the explicit parameters you passed.</p>
<p>You can use multiple parameters by separating them using a comma.</p>
<p>Notice I used an arrow function. We avoid arrow functions in methods and computed properties, generally, because they almost always reference <code>this</code> to access the component data. But in this case, the filter does not need to access <code>this</code> but receives all the data it needs through the parameters, and we can safely use the simpler arrow function syntax.</p>
<p><a target="_blank" href="https://www.npmjs.com/package/vue2-filters">This package</a> has a lot of pre-made filters for you to use directly in templates, which include <code>capitalize</code>, <code>uppercase</code>, <code>lowercase</code>, <code>placeholder</code>, <code>truncate</code>, <code>currency</code>, <code>pluralize</code> and more.</p>
<h3 id="heading-communication-among-components">Communication among components</h3>
<p>Components in Vue can communicate in various ways.</p>
<h4 id="heading-using-props">Using Props</h4>
<p>The first way is by using props.</p>
<p>Parents “pass down” data by adding arguments to the component declaration:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">Car</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"green"</span> /&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">import</span> Car <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Car'</span>
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">name</span>: <span class="hljs-string">'App'</span>,  <span class="hljs-attr">components</span>: {    Car  }}&lt;/script&gt;
</code></pre><p>Props are one-way: from parent to child. Any time the parent changes the prop, the new value is sent to the child and re-rendered.</p>
<p>The reverse is not true, and you should never mutate a prop inside the child component.</p>
<h4 id="heading-using-events-to-communicate-from-children-to-parent">Using Events to communicate from children to parent</h4>
<p>Events allow you to communicate from the children up to the parent:</p>
<pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">name</span>: <span class="hljs-string">'Car'</span>,  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClick</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      <span class="hljs-built_in">this</span>.$emit(<span class="hljs-string">'clickedSomething'</span>)    }  }}&lt;/script&gt;
</code></pre><p>The parent can intercept this using the <code>v-on</code> directive when including the component in its template:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">Car</span> <span class="hljs-attr">v-on:clickedSomething</span>=<span class="hljs-string">"handleClickInParent"</span> /&gt;</span>    <span class="hljs-comment">&lt;!-- or --&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">Car</span> @<span class="hljs-attr">clickedSomething</span>=<span class="hljs-string">"handleClickInParent"</span> /&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">name</span>: <span class="hljs-string">'App'</span>,  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClickInParent</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      <span class="hljs-comment">//...    }  }}&lt;/script&gt;</span>
</code></pre><p>You can pass parameters of course:</p>
<pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">name</span>: <span class="hljs-string">'Car'</span>,  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClick</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      <span class="hljs-built_in">this</span>.$emit(<span class="hljs-string">'clickedSomething'</span>, param1, param2)    }  }}&lt;/script&gt;
</code></pre><p>and retrieve them from the parent:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">Car</span> <span class="hljs-attr">v-on:clickedSomething</span>=<span class="hljs-string">"handleClickInParent"</span> /&gt;</span>    <span class="hljs-comment">&lt;!-- or --&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">Car</span> @<span class="hljs-attr">clickedSomething</span>=<span class="hljs-string">"handleClickInParent"</span> /&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">name</span>: <span class="hljs-string">'App'</span>,  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClickInParent</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">param1, param2</span>) </span>{      <span class="hljs-comment">//...    }  }}&lt;/script&gt;</span>
</code></pre><h4 id="heading-using-an-event-bus-to-communicate-between-any-components">Using an Event Bus to communicate between any components</h4>
<p>Using events you’re not limited to child-parent relationships. You can use the so-called Event Bus.</p>
<p>Above we used <code>this.$emit</code> to emit an event on the component instance.</p>
<p>What we can do instead is to emit the event on a more generally accessible component.</p>
<p><code>this.$root</code>, the root component, is commonly used for this.</p>
<p>You can also create a Vue component dedicated to this job, and import it where you need.</p>
<pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">name</span>: <span class="hljs-string">'Car'</span>,  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">handleClick</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{      <span class="hljs-built_in">this</span>.$root.$emit(<span class="hljs-string">'clickedSomething'</span>)    }  }}&lt;/script&gt;
</code></pre><p>Any other component can listen for this event. You can do so in the <code>mounted</code> callback:</p>
<pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">name</span>: <span class="hljs-string">'App'</span>,  mounted() {    <span class="hljs-built_in">this</span>.$root.$on(<span class="hljs-string">'clickedSomething'</span>, <span class="hljs-function">() =&gt;</span> {      <span class="hljs-comment">//...    })  }}&lt;/script&gt;</span>
</code></pre><p>This is what Vue provides out of the box.</p>
<p>When you outgrow this, you can look into Vuex or other 3rd part libraries.</p>
<h3 id="heading-manage-state-using-vuex">Manage state using Vuex</h3>
<p>Vuex is the official state management library for Vue.js.</p>
<p>Its job is to share data across the components of your application.</p>
<p>Components in Vue.js out of the box can communicate using</p>
<ul>
<li>props, to pass state down to child components from a parent</li>
<li>events, to change the state of a parent component from a child, or using the root component as an event bus</li>
</ul>
<p>Sometimes things get more complex than what these simple options allow.</p>
<p>In this case, a good option is to centralize the state in a single store. This is what Vuex does.</p>
<h4 id="heading-why-should-you-use-vuex">Why should you use Vuex?</h4>
<p>Vuex is not the only state management option you can use in Vue (you can use <a target="_blank" href="https://medium.com/@quincylarson/17a99705b8e1">Redux</a> too), but its main advantage is that it’s official, and its integration with Vue.js is what makes it shine.</p>
<p>With React you have the trouble of having to choose one of the many libraries available, as the ecosystem is huge and has no actual standard. Lately Redux was the most popular choice, with <a target="_blank" href="https://mobx.js.org/getting-started.html">MobX</a> following up in terms of popularity. With Vue I’d go as far as to say that you won’t need to look around for anything other than Vuex, especially when starting out.</p>
<p>Vuex borrowed many of its ideas from the React ecosystem, as this is the Flux pattern popularized by Redux.</p>
<p>If you know Flux or Redux already, Vuex will be very familiar. If you don’t, no problem — I’ll explain every concept from the ground up.</p>
<p>Components in a Vue application can have their own state. For example, an input box will store the data entered into it locally. This is perfectly fine, and components can have local state even when using Vuex.</p>
<p>You know that you need something like Vuex when you start doing a lot of work to pass a piece of state around.</p>
<p>In this case, Vuex provides a central repository store for the state, and you mutate the state by asking the store to do that.</p>
<p>Every component that depends on a particular piece of the state will access it using a getter on the store, which makes sure it’s updated as soon as that thing changes.</p>
<p>Using Vuex will introduce some complexity into the application, as things need to be set up in a certain way to work correctly. But if this helps solve the unorganized props passing and event system that might grow into a spaghetti mess if too complicated, then it’s a good choice.</p>
<h4 id="heading-lets-start">Let’s start</h4>
<p>In this example, I’m starting from a Vue CLI application. Vuex can be used also by directly loading it into a script tag. But, since Vuex is more in tune with bigger applications, it’s much more likely you will use it on a more structured application, like the ones you can start up quickly with the Vue CLI.</p>
<p>The examples I use will be put CodeSandbox, which is a great service that has a Vue CLI <a target="_blank" href="https://codesandbox.io/s/vue">sample</a> ready to go. I recommend using it to play around.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/hoB1Mu8Q1Py50t5Es5EKze26BsJOApMhEWVh" alt="Image" width="800" height="500" loading="lazy"></p>
<p>Once you’re there, click the Add dependency button, enter “vuex” and click it.</p>
<p>Now Vuex will be listed in the project dependencies.</p>
<p>To install Vuex locally you can simply run <code>npm install vuex</code> or <code>yarn add vuex</code> inside the project folder.</p>
<h4 id="heading-create-the-vuex-store">Create the Vuex store</h4>
<p>Now we are ready to create our Vuex store.</p>
<p>This file can be put anywhere. It’s generally suggested to put it in the <code>src/store/store.js</code> file, so we'll do that.</p>
<p>In this file we initialize Vuex and tell Vue to use it:</p>
<pre><code><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span><span class="hljs-keyword">import</span> Vuex <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex'</span>
</code></pre><pre><code>Vue.use(Vuex)
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> store = <span class="hljs-keyword">new</span> Vuex.Store({})
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/p2kPCCKdhaHsHfXd4Nti975YVgvKMnbHbMRd" alt="Image" width="800" height="500" loading="lazy"></p>
<p>We export a Vuex store object, which we create using the <code>Vuex.Store()</code> API.</p>
<h4 id="heading-a-use-case-for-the-store">A use case for the store</h4>
<p>Now that we have a skeleton in place, let’s come up with an idea for a good use case for Vuex, so I can introduce its concepts.</p>
<p>For example, I have two sibling components, one with an input field, and one that prints that input field content.</p>
<p>When the input field is changed, I want to also change the content in that second component. Very simple, but this will do the job for us.</p>
<h4 id="heading-introducing-the-new-components-we-need">Introducing the new components we need</h4>
<p>I delete the HelloWorld component and add a Form component, and a Display component.</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"flavor"</span>&gt;</span>Favorite ice cream flavor?<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"flavor"</span>&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span></span>
</code></pre><pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>You chose ???<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>&lt;/template&gt;
</code></pre><h4 id="heading-adding-those-components-to-the-app">Adding those components to the app</h4>
<p>We add them to the <code>App.vue</code> code instead of the HelloWorld component:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">Form</span>/&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">Display</span>/&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">import</span> Form <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Form'</span><span class="hljs-keyword">import</span> Display <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Display'</span>
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">name</span>: <span class="hljs-string">'App'</span>,  <span class="hljs-attr">components</span>: {    Form,    Display  }}&lt;/script&gt;
</code></pre><h4 id="heading-add-the-state-to-the-store">Add the state to the store</h4>
<p>So with this in place, we go back to the store.js file. We add a property to the store called <code>state</code>, which is an object, that contains the <code>flavor</code> property. That's an empty string initially.</p>
<pre><code><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span><span class="hljs-keyword">import</span> Vuex <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex'</span>
</code></pre><pre><code>Vue.use(Vuex)
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> store = <span class="hljs-keyword">new</span> Vuex.Store({  <span class="hljs-attr">state</span>: {    <span class="hljs-attr">flavor</span>: <span class="hljs-string">''</span>  }})
</code></pre><p>We’ll update it when the user types into the input field.</p>
<h4 id="heading-add-a-mutation">Add a mutation</h4>
<p>The state cannot be manipulated except by using mutations. We set up one mutation which will be used inside the <code>Form</code> component to notify the store that the state should change.</p>
<pre><code><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span><span class="hljs-keyword">import</span> Vuex <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex'</span>
</code></pre><pre><code>Vue.use(Vuex)
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> store = <span class="hljs-keyword">new</span> Vuex.Store({  <span class="hljs-attr">state</span>: {    <span class="hljs-attr">flavor</span>: <span class="hljs-string">''</span>  },  <span class="hljs-attr">mutations</span>: {    change(state, flavor) {      state.flavor = flavor    }  }})
</code></pre><h4 id="heading-add-a-getter-to-reference-a-state-property">Add a getter to reference a state property</h4>
<p>With that set, we need to add a way to look at the state. We do so using getters. We set up a getter for the <code>flavor</code>property:</p>
<pre><code><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span><span class="hljs-keyword">import</span> Vuex <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex'</span>
</code></pre><pre><code>Vue.use(Vuex)
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> store = <span class="hljs-keyword">new</span> Vuex.Store({  <span class="hljs-attr">state</span>: {    <span class="hljs-attr">flavor</span>: <span class="hljs-string">''</span>  },  <span class="hljs-attr">mutations</span>: {    change(state, flavor) {      state.flavor = flavor    }  },  <span class="hljs-attr">getters</span>: {    <span class="hljs-attr">flavor</span>: <span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.flavor  }})
</code></pre><p>Notice how <code>getters</code> is an object. <code>flavor</code> is a property of this object, which accepts the state as the parameter, and returns the <code>flavor</code> property of the state.</p>
<h4 id="heading-adding-the-vuex-store-to-the-app">Adding the Vuex store to the app</h4>
<p>Now the store is ready to be used. We go back to our application code, and in the main.js file, we need to import the state and make it available in our Vue app.</p>
<p>We add</p>
<pre><code><span class="hljs-keyword">import</span> { store } <span class="hljs-keyword">from</span> <span class="hljs-string">'./store/store'</span>
</code></pre><p>and we add it to the Vue application:</p>
<pre><code><span class="hljs-keyword">new</span> Vue({  <span class="hljs-attr">el</span>: <span class="hljs-string">'#app'</span>,  store,  <span class="hljs-attr">components</span>: { App },  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;App/&gt;'</span>})
</code></pre><p>Once we add this, since this is the main Vue component, the <code>store</code> variable inside every Vue component will point to the Vuex store.</p>
<h4 id="heading-update-the-state-on-a-user-action-using-commit">Update the state on a user action using commit</h4>
<p>Let’s update the state when the user types something.</p>
<p>We do so by using the <code>store.commit()</code> API.</p>
<p>But first, let’s create a method that is invoked when the input content changes. We use <code>@input</code> rather than <code>@change</code>because the latter is only triggered when the focus is moved away from the input box, while <code>@input</code> is called on every keypress.</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"flavor"</span>&gt;</span>Favorite ice cream flavor?<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> @<span class="hljs-attr">input</span>=<span class="hljs-string">"changed"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"flavor"</span>&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span></span>
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">changed</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>) </span>{      alert(event.target.value)    }  }}&lt;/script&gt;
</code></pre><p>Now that we have the value of the flavor, we use the Vuex API:</p>
<pre><code>&lt;script&gt;<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {  <span class="hljs-attr">methods</span>: {    <span class="hljs-attr">changed</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>) </span>{      <span class="hljs-built_in">this</span>.$store.commit(<span class="hljs-string">'change'</span>, event.target.value)    }  }}&lt;/script&gt;
</code></pre><p>See how we reference the store using <code>this.$store</code>? This is thanks to the inclusion of the <code>store</code> object in the main Vue component initialization.</p>
<p>The <code>commit()</code> method accepts a mutation name (we used <code>change</code> in the Vuex store) and a payload, which will be passed to the mutation as the second parameter of its callback function.</p>
<h4 id="heading-use-the-getter-to-print-the-state-value">Use the getter to print the state value</h4>
<p>Now we need to reference the getter of this value in the Display template, by using <code>$store.getters.flavor</code>. <code>this</code> can be removed because we're in the template, and <code>this</code> is implicit.</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>You chose {{ $store.getters.flavor }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>&lt;/template&gt;
</code></pre><p>The full, working source code is available <a target="_blank" href="https://codesandbox.io/s/zq7k7nkzkm">here</a>.</p>
<p>There are still many concepts missing in this puzzle:</p>
<ul>
<li>actions</li>
<li>modules</li>
<li>helpers</li>
<li>plugins</li>
</ul>
<p>But now you have the basics to go and read about them in the official docs.</p>
<h3 id="heading-handle-urls-using-vue-router">Handle URLs using Vue Router</h3>
<p>In a JavaScript web application, a router is the part that syncs the currently displayed view with the browser address bar content.</p>
<p>In other words, it’s the part that makes the URL change when you click something in the page, and helps to show the correct view when you hit a specific URL.</p>
<p>Traditionally, the Web is built around URLs. When you hit a certain URL, a specific page is displayed.</p>
<p>With the introduction of applications that run inside the browser and change what the user sees, many applications broke this interaction, and you had to manually update the URL with the browser’s History API.</p>
<p>You need a router when you need to sync URLs to views in your app. It’s a very common need, and all the major modern frameworks now allow you to manage routing.</p>
<p>The Vue Router library is the way to go for Vue.js applications. Vue does not enforce the use of this library. You can use whatever generic routing library you want, or also create your own History API integration, but the benefit of using Vue Router is that it’s official.</p>
<p>This means it’s maintained by the same people who maintain Vue, so you get a more consistent integration in the framework, and the guarantee that it’s always going to be compatible in the future, no matter what.</p>
<h4 id="heading-installation-1">Installation</h4>
<p>Vue Router is available via npm with the package named <code>vue-router</code>.</p>
<p>If you use Vue via a script tag, you can include Vue Router using</p>
<pre><code>&lt;script src=<span class="hljs-string">"https://unpkg.com/vue-router"</span>&gt;&lt;/script&gt;
</code></pre><p><a target="_blank" href="https://unpkg.com/#/">UNPKG</a> is a very handy tool that makes every npm package available in the browser with a simple link.</p>
<p>If you use the Vue CLI, install it using:</p>
<pre><code>npm install vue-router
</code></pre><p>Once you install <code>vue-router</code> and make it available either using a script tag or via Vue CLI, you can now import it in your app.</p>
<p>You import it after <code>vue</code>, and you call <code>Vue.use(VueRouter)</code> to <strong>install</strong> it inside the app:</p>
<pre><code><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span><span class="hljs-keyword">import</span> VueRouter <span class="hljs-keyword">from</span> <span class="hljs-string">'vue-router'</span>
</code></pre><pre><code>Vue.use(VueRouter)
</code></pre><p>After you call <code>Vue.use()</code> passing the router object, in any component of the app you have access to these objects:</p>
<ul>
<li><code>this.$router</code> is the router object</li>
<li><code>this.$route</code> is the current route object</li>
</ul>
<h4 id="heading-the-router-object">The router object</h4>
<p>The router object, accessed using <code>this.$router</code> from any component when the Vue Router is installed in the root Vue component, offers many nice features.</p>
<p>We can make the app navigate to a new route using</p>
<ul>
<li><code>this.$router.push()</code></li>
<li><code>this.$router.replace()</code></li>
<li><code>this.$router.go()</code></li>
</ul>
<p>which resemble the <code>pushState</code>, <code>replaceState</code> and <code>go</code> methods of the History API.</p>
<ul>
<li><code>push()</code> is used to go to a new route, adding a new item to the browser history</li>
<li><code>replace()</code> is the same, except it does not push a new state to the history</li>
</ul>
<p>Usage samples:</p>
<pre><code><span class="hljs-built_in">this</span>.$router.push(<span class="hljs-string">'about'</span>) <span class="hljs-comment">//named route, see laterthis.$router.push({ path: 'about' })this.$router.push({ path: 'post', query: { post_slug: 'hello-world' } }) //using query parameters (post?post_slug=hello-world)this.$router.replace({ path: 'about' })</span>
</code></pre><p><code>go()</code> goes back and forth, accepting a number that can be positive or negative to go back in the history:</p>
<pre><code><span class="hljs-built_in">this</span>.$router.go(<span class="hljs-number">-1</span>) <span class="hljs-comment">//go back 1 stepthis.$router.go(1) //go forward 1 step</span>
</code></pre><h4 id="heading-defining-the-routes">Defining the routes</h4>
<p>I’m using a Vue Single File Component in this example.</p>
<p>In the template I use a <code>nav</code> tag that has three <code>router-link</code> components, which have the labels Home, Login, and About. A URL is assigned through the <code>to</code> attribute.</p>
<p>The <code>router-view</code> component is where the Vue Router will put the content that matches the current URL.</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>      <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span>      <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/login"</span>&gt;</span>Login<span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span>      <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/about"</span>&gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span>    <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">router-view</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">router-view</span>&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>&lt;/template&gt;
</code></pre><p>A <code>router-link</code> component renders an <code>a</code> tag by default (you can change that). Every time the route changes, either by clicking a link or by changing the URL, a <code>router-link-active</code> class is added to the element that refers to the active route, allowing you to style it.</p>
<p>In the JavaScript part, we first include and install the router, then we define three route components.</p>
<p>We pass them to the initialization of the <code>router</code> object, and we pass this object to the Vue root instance.</p>
<p>Here’s the code:</p>
<pre><code>&lt;script&gt;<span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span><span class="hljs-keyword">import</span> VueRouter <span class="hljs-keyword">from</span> <span class="hljs-string">'vue-router'</span>
</code></pre><pre><code>Vue.use(Router)
</code></pre><pre><code><span class="hljs-keyword">const</span> Home  = {  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;div&gt;Home&lt;/div&gt;'</span>}
</code></pre><pre><code><span class="hljs-keyword">const</span> Login = {  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;div&gt;Login&lt;/div&gt;'</span>}
</code></pre><pre><code><span class="hljs-keyword">const</span> About = {  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;div&gt;About&lt;/div&gt;'</span>}
</code></pre><pre><code><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> VueRouter({  <span class="hljs-attr">routes</span>: [    { <span class="hljs-attr">path</span>: <span class="hljs-string">'/'</span>, <span class="hljs-attr">component</span>: Home },    { <span class="hljs-attr">path</span>: <span class="hljs-string">'/login'</span>, <span class="hljs-attr">component</span>: Login },    { <span class="hljs-attr">path</span>: <span class="hljs-string">'/about'</span>, <span class="hljs-attr">component</span>: About }  ]})
</code></pre><pre><code><span class="hljs-keyword">new</span> Vue({  router}).$mount(<span class="hljs-string">'#app'</span>)&lt;/script&gt;
</code></pre><p>Usually, in a Vue app, you instantiate and mount the root app using:</p>
<pre><code><span class="hljs-keyword">new</span> Vue({  <span class="hljs-attr">render</span>: <span class="hljs-function"><span class="hljs-params">h</span> =&gt;</span> h(App)}).$mount(<span class="hljs-string">'#app'</span>)
</code></pre><p>When using the Vue Router, you don’t pass a <code>render</code> property but instead, you use <code>router</code>.</p>
<p>The syntax used in the above example:</p>
<pre><code><span class="hljs-keyword">new</span> Vue({  router}).$mount(<span class="hljs-string">'#app'</span>)
</code></pre><p>is shorthand for:</p>
<pre><code><span class="hljs-keyword">new</span> Vue({  <span class="hljs-attr">router</span>: router}).$mount(<span class="hljs-string">'#app'</span>)
</code></pre><p>See in the example, we pass a <code>routes</code> array to the <code>VueRouter</code> constructor. Each route in this array has a <code>path</code> and <code>component</code> params.</p>
<p>If you pass a <code>name</code> param too, you have a named route.</p>
<h4 id="heading-using-named-routes-to-pass-parameters-to-the-router-push-and-replace-methods">Using named routes to pass parameters to the router push and replace methods</h4>
<p>Remember how we used the Router object to push a new state before?</p>
<pre><code><span class="hljs-built_in">this</span>.$router.push({ <span class="hljs-attr">path</span>: <span class="hljs-string">'about'</span> })
</code></pre><p>With a named route we can pass parameters to the new route:</p>
<pre><code><span class="hljs-built_in">this</span>.$router.push({ <span class="hljs-attr">name</span>: <span class="hljs-string">'post'</span>, <span class="hljs-attr">params</span>: { <span class="hljs-attr">post_slug</span>: <span class="hljs-string">'hello-world'</span> } })
</code></pre><p>The same goes for <code>replace()</code>:</p>
<pre><code><span class="hljs-built_in">this</span>.$router.replace({ <span class="hljs-attr">name</span>: <span class="hljs-string">'post'</span>, <span class="hljs-attr">params</span>: { <span class="hljs-attr">post_slug</span>: <span class="hljs-string">'hello-world'</span> } })
</code></pre><h4 id="heading-what-happens-when-a-user-clicks-a-router-link">What happens when a user clicks a <code>router-link?</code></h4>
<p>The application will render the route component that matches the URL passed to the link.</p>
<p>The new route component that handles the URL is instantiated and its guards called, and the old route component will be destroyed.</p>
<h4 id="heading-route-guards">Route guards</h4>
<p>Since we mentioned guards, let’s introduce them.</p>
<p>You can think of them as life cycle hooks or middleware. Those are functions called at specific times during the execution of the application. You can jump in and alter the execution of a route, redirecting or simply canceling the request.</p>
<p>You can have global guards by adding a callback to the <code>beforeEach()</code> and <code>afterEach()</code> property of the router.</p>
<ul>
<li><code>beforeEach()</code> is called before the navigation is confirmed</li>
<li><code>beforeResolve()</code> is called when <code>beforeEach()</code> is executed and all the components <code>beforeRouterEnter</code> and <code>beforeRouteUpdate</code> guards are called, but before the navigation is confirmed. The final check.</li>
<li><code>afterEach()</code> is called after the navigation is confirmed</li>
</ul>
<p>What does “the navigation is confirmed” mean? We’ll see it in a second. In the meantime think of it as “the app can go to that route”.</p>
<p>The usage is:</p>
<pre><code><span class="hljs-built_in">this</span>.$router.beforeEach(<span class="hljs-function">(<span class="hljs-params">to, <span class="hljs-keyword">from</span>, next</span>) =&gt;</span> {  <span class="hljs-comment">// ...})</span>
</code></pre><pre><code><span class="hljs-built_in">this</span>.$router.afterEach(<span class="hljs-function">(<span class="hljs-params">to, <span class="hljs-keyword">from</span></span>) =&gt;</span> {  <span class="hljs-comment">// ...})</span>
</code></pre><p><code>to</code> and <code>from</code> represent the route objects that we go to and from.</p>
<p><code>beforeEach</code> has an additional parameter <code>next</code> which if we call with <code>false</code> as the parameter, will block the navigation and cause it to be unconfirmed.</p>
<p>Like in Node middleware, if you're familiar, <code>next()</code> should always be called, otherwise execution will get stuck.</p>
<p>Single route components also have guards:</p>
<ul>
<li><code>beforeRouteEnter(from, to, next)</code> is called before the current route is confirmed</li>
<li><code>beforeRouteUpdate(from, to, next)</code> is called when the route changes but the component that manages it is still the same (with dynamic routing, see <code>next</code>)</li>
<li><code>beforeRouteLeave(from, to, next)</code> is called when we move away from here</li>
</ul>
<p>We mentioned navigation. To determine if the navigation to a route is confirmed, Vue Router performs some checks:</p>
<ul>
<li>it calls <code>beforeRouteLeave</code> guard in the current component(s)</li>
<li>it calls the router <code>beforeEach()</code> guard</li>
<li>it calls the <code>beforeRouteUpdate()</code> in any component that needs to be reused, if any exist</li>
<li>it calls the <code>beforeEnter()</code> guard on the route object (I didn't mention it but you can look <a target="_blank" href="https://router.vuejs.org/guide/advanced/navigation-guards.html#per-route-guard">here</a>)</li>
<li>it calls the <code>beforeRouterEnter()</code> in the component that we should enter into</li>
<li>it calls the router <code>beforeResolve()</code> guard</li>
<li>if all was fine, the navigation is confirmed!</li>
<li>it calls the router <code>afterEach()</code> guard</li>
</ul>
<p>You can use the route-specific guards (<code>beforeRouteEnter</code> and <code>beforeRouteUpdate</code> in case of dynamic routing) as life cycle hooks, so you can start data fetching requests for example.</p>
<h4 id="heading-dynamic-routing">Dynamic routing</h4>
<p>The example above shows a different view based on the URL, handling the <code>/</code>, <code>/login</code> and <code>/about</code> routes.</p>
<p>A very common need is to handle dynamic routes, like having all posts under <code>/post/</code>, each with the slug name:</p>
<ul>
<li><code>/post/first</code></li>
<li><code>/post/another-post</code></li>
<li><code>/post/hello-world</code></li>
</ul>
<p>You can achieve this using a dynamic segment.</p>
<p>Those were static segments:</p>
<pre><code><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> VueRouter({  <span class="hljs-attr">routes</span>: [    { <span class="hljs-attr">path</span>: <span class="hljs-string">'/'</span>, <span class="hljs-attr">component</span>: Home },    { <span class="hljs-attr">path</span>: <span class="hljs-string">'/login'</span>, <span class="hljs-attr">component</span>: Login },    { <span class="hljs-attr">path</span>: <span class="hljs-string">'/about'</span>, <span class="hljs-attr">component</span>: About }  ]})
</code></pre><p>We add in a dynamic segment to handle blog posts:</p>
<pre><code><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> VueRouter({  <span class="hljs-attr">routes</span>: [    { <span class="hljs-attr">path</span>: <span class="hljs-string">'/'</span>, <span class="hljs-attr">component</span>: Home },    { <span class="hljs-attr">path</span>: <span class="hljs-string">'/post/:post_slug'</span>, <span class="hljs-attr">component</span>: Post },    { <span class="hljs-attr">path</span>: <span class="hljs-string">'/login'</span>, <span class="hljs-attr">component</span>: Login },    { <span class="hljs-attr">path</span>: <span class="hljs-string">'/about'</span>, <span class="hljs-attr">component</span>: About }  ]})
</code></pre><p>Notice the <code>:post_slug</code> syntax. This means that you can use any string, and that will be mapped to the <code>post_slug</code>placeholder.</p>
<p>You’re not limited to this kind of syntax. Vue relies on <a target="_blank" href="https://github.com/pillarjs/path-to-regexp">this library</a> to parse dynamic routes, and you can go wild with Regular Expressions.</p>
<p>Now inside the Post route component we can reference the route using <code>$route</code>, and the post slug using <code>$route.params.post_slug</code>:</p>
<pre><code><span class="hljs-keyword">const</span> Post = {  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;div&gt;Post: {{ $route.params.post_slug }}&lt;/div&gt;'</span>}
</code></pre><p>We can use this parameter to load the contents from the back-end.</p>
<p>You can have as many dynamic segments as you want, in the same URL:</p>
<p><code>/post/:author/:post_slug</code></p>
<p>Remember before when we talked about what happens when a user navigates to a new route?</p>
<p>In the case of dynamic routes, what happens is a little different.</p>
<p>For Vue to be more efficient, instead of destroying the current route component and re-instantiating it, it reuses the current instance.</p>
<p>When this happens, Vue calls the <code>beforeRouteUpdate</code> life cycle event.</p>
<p>There you can perform any operation you need:</p>
<pre><code><span class="hljs-keyword">const</span> Post = {  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;div&gt;Post: {{ $route.params.post_slug }}&lt;/div&gt;'</span>  beforeRouteUpdate(to, <span class="hljs-keyword">from</span>, next) {    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Updating slug from <span class="hljs-subst">${<span class="hljs-keyword">from</span>}</span> to <span class="hljs-subst">${to}</span>`</span>)    next() <span class="hljs-comment">//make sure you always call next()  }}</span>
</code></pre><h4 id="heading-using-props-1">Using props</h4>
<p>In the examples, I used <code>$route.params.*</code> to access the route data. A component should not be so tightly coupled with the router, and instead, we can use props:</p>
<pre><code><span class="hljs-keyword">const</span> Post = {  <span class="hljs-attr">props</span>: [<span class="hljs-string">'post_slug'</span>],  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;div&gt;Post: {{ post_slug }}&lt;/div&gt;'</span>}
</code></pre><pre><code><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> VueRouter({  <span class="hljs-attr">routes</span>: [    { <span class="hljs-attr">path</span>: <span class="hljs-string">'/post/:post_slug'</span>, <span class="hljs-attr">component</span>: Post, <span class="hljs-attr">props</span>: <span class="hljs-literal">true</span> }  ]})
</code></pre><p>Notice the <code>props: true</code> passed to the route object to enable this functionality.</p>
<h4 id="heading-nested-routes">Nested routes</h4>
<p>Before I mentioned that you can have as many dynamic segments as you want, in the same URL, like:</p>
<p><code>/post/:author/:post_slug</code></p>
<p>So, say we have an Author component taking care of the first dynamic segment:</p>
<pre><code>&lt;template&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">router-view</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">router-view</span>&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>&lt;/template&gt;
</code></pre><pre><code>&lt;script&gt;<span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span><span class="hljs-keyword">import</span> VueRouter <span class="hljs-keyword">from</span> <span class="hljs-string">'vue-router'</span>
</code></pre><pre><code>Vue.use(Router)
</code></pre><pre><code><span class="hljs-keyword">const</span> Author  = {  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;div&gt;Author: {{ $route.params.author}}&lt;/div&gt;'</span>}
</code></pre><pre><code><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> VueRouter({  <span class="hljs-attr">routes</span>: [    { <span class="hljs-attr">path</span>: <span class="hljs-string">'/post/:author'</span>, <span class="hljs-attr">component</span>: Author }  ]})
</code></pre><pre><code><span class="hljs-keyword">new</span> Vue({  router}).$mount(<span class="hljs-string">'#app'</span>)&lt;/script&gt;
</code></pre><p>We can insert a second <code>router-view</code> component instance inside the Author template:</p>
<pre><code><span class="hljs-keyword">const</span> Author  = {  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;div&gt;Author: {{ $route.params.author}}&lt;router-view&gt;&lt;/router-view&gt;&lt;/div&gt;'</span>}
</code></pre><p>We add the Post component:</p>
<pre><code><span class="hljs-keyword">const</span> Post = {  <span class="hljs-attr">template</span>: <span class="hljs-string">'&lt;div&gt;Post: {{ $route.params.post_slug }}&lt;/div&gt;'</span>}
</code></pre><p>Then we’ll inject the inner dynamic route in the <code>VueRouter</code> configuration:</p>
<pre><code><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> VueRouter({  <span class="hljs-attr">routes</span>: [{    <span class="hljs-attr">path</span>: <span class="hljs-string">'/post/:author'</span>,    <span class="hljs-attr">component</span>: Author,    <span class="hljs-attr">children</span>: [      path: <span class="hljs-string">':post_slug'</span>,      <span class="hljs-attr">component</span>: Post    ]  }]})
</code></pre><p>Thank you for reading!</p>
<blockquote>
<p>Get this post PDF/ePub/Kindle ebook at <a target="_blank" href="https://vuehandbook.com">vuehandbook.com</a></p>
</blockquote>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
