Build a Shopping List App with the Vue 3.0 Composition API

Deven Rathore
Share

This article will show how the Vue Composition API is a great way to make your code more readable and maintainable. An alternative to the Options API, the Composition API introduced in Vue 3 handles methods and component state more accessibly.

The Composition API is a new (and optional) way of creating and organizing components in a Vue 3 application. It allows reactive component logic to be defined more intuitively by allowing all the code for a specific feature (search, for example) to be grouped. Using the Vue Composition API will make your application more scalable and reusable between several components.

In this article, we’ll build a simple shopping List app with the Vue Composition API.

Shopping list app with Vue Composition API

You can check out a live demo of the app we’re building.

Prerequisites

For this tutorial, you’ll need:

  • a basic understanding of HTML, CSS, JavaScript, and Vue
  • a text editor
  • a web browser
  • Node.js
  • Vue CLI

Setting Up the Vue Application

Now let’s start by installing Vue Cli:

npm install -g vue-cli

This command will install Vue globally.

We’ll use the Vue CLI to build a simple application. To do that, open up your terminal and type the following:

vue create vueshoppinglist

After installation, move into the folder using the cd vueshoppinglist and run npm run serve.

Your new Vue installation is ready

This starts a development server that allows you to view your app on localhost:8080.

It’s now time to set up a nice Vue project.

The Vue Composition API

To Install the Composition API from the root of your project, run the following:

npm install --save @vue/composition-api

After successfully installing, we’ll import it into our project.

Modify src/main.vue to register the Composition API globally in our application, so that we can use it in all our application components:

import Vue from 'vue'
import App from './App.vue'
import VueCompositionApi from '@vue/composition-api'
Vue.config.productionTip = false
Vue.use(VueCompositionApi)
new Vue({
  render: h => h(App),
}).$mount('#app')

Building Out the User Interface

We’ll need a component that will house the UI of our app. Create a new ShoppingList.vue component in the src/components/ directory and paste the following into the file:

<template>
  <section>
    <div class="form-container">
      <h2>Add Item</h2>
      <form>
        <div>
          <label>Product name</label>
          <br />
          <input type="text" />
        </div>
        <div>
          <button type="submit" class="submit">Add Item</button>
        </div>
      </form>
    </div>
    <div class="list-container">
      <ul>
        <li>
          Shopping List app
          <span style="float:right;padding-right:10px;">
            <button>X</button>
          </span>
        </li>
      </ul>
    </div>
  </section>
</template>
<script>
export default {};
</script>
<style scoped>
input {
  width: 20%;
  height: 30px;
  border: 2px solid green;
}
.submit {
  margin: 10px;
  padding: 10px;
  border-radius: 0px;
  border: 0px;
  background: green;
  color: white;
}
ul li {
  list-style: none;
  border: 2px solid green;
  width: 30%;
  margin-top: 10px;
}
</style>

The code snippet above is the initial boilerplate of our UI. We’ll now import our new component ShoppingList.vue to App.vue as shown below:

<template>
  <div id="app">
    <img alt="Shoppingd List" src="./assets/shopping.png">
    <shopping-list msg="Welcome to Your Vue.js App"/>
  </div>
</template>
<script>
import ShoppingList from './components/ShoppingList.vue'
export default {
  name: 'App',
  components: {
    ShoppingList
  }
}
</script>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Working with the Vue Composition API

Let’s get started by importing the Composition API to our component ShoppingList.Vue:

<script>
import { reactive } from "@vue/composition-api";
export default {};
</script>

Here, we’re importing reactive from the Vue Composition API.

We’ll now add some event listeners to the application by modifying our template to this:

<template>
  <section>
    <div class="form-container">
      <h2>My Shopping List App</h2>
      <form @submit.prevent="addItem">
        <div>
          <label> Product Name</label>
          <br />
          <input v-model="state.input" type="text" />
        </div>
        <div>
          <button type="submit" class="submit">Add Item</button>
        </div>
      </form>
    </div>
    <div class="list-container">
      <ul v-for="(Item,index) in state.Items" :key="index">
        <li>
          {{Item}}
          <span style="float:right;padding-right:10px;">
            <button @click="removeItem(index)">X</button>
          </span>
        </li>
      </ul>
    </div>
  </section>
</template>

Vue 3 uses the data and methods option to define state and add functions rather than accessing to a setup method. This method is called after the lifecycle hook beforeCreate and prior to create.

We’ll now declare the state variable and methods inside the setup method, as shown below:

<script>
  import { reactive } from "@vue/composition-api";
  export default {
  setup() {
      const { state, addItem, removeItem } = ItemList();
      return { state, addItem, removeItem };
    }
  };
</script>

After declaring Variables and methods, we need to define our component state:

<script>
import { reactive } from "@vue/composition-api";
export default {
setup() {
  const { state, addItem, removeItem } = ItemList();
  return { state, addItem, removeItem };
}
};
function ItemList() {
let state = reactive({
  input: "",
  Items: ["Grocery"]
});
return { state };
</script>

The state here is scoped to the ItemList function. We define our input state that we’ll bind to our input field and also define our Items array that will hold all our Items.

Let’s define our addItem function:

<script>
import { reactive } from "@vue/composition-api";
export default {
setup() {
    const { state, addItem, removeItem } = ItemList();
    return { state, addItem, removeItem };
  }
};
function ItemList() {
  let state = reactive({
    input: "",
    Items: ["Grocery"]
  });
 let addItem = () => {
    state.Items.push(state.input);
    state.input = "";
  };
  return { state, addItem };
</script>

The add functionality will take the data in the input field and push it into the Items array using the push method.

Let’s implement deleting an item. We’ll get the index of the Item and then remove the Item from the users array using the splice method:

<script>
import { reactive } from "@vue/composition-api";
export default {
setup() {
    const { state, addItem, removeItem } = ItemList();
    return { state, addItem, removeItem };
  }
};
function ItemList() {
  let state = reactive({
    input: "",
    Items: ["Grocery"]
  });
 let addItem = () => {
    state.Items.push(state.input);
    state.input = "";
  };

 let removeItem = i => {
    state.Items.splice(i, 1);
  };
  return { state, addItem, removeItem };
</script>

It’s important that everything we want to be able to access from the template is returned by both the itemList and setup() methods. At the end of the code snippet, we’re returning the state or method.

Our shopping list app is now complete:

The shopping app ready to go

Conclusion

Finally, we’ve built our Shopping List app with the Vue 3 Composition API. It’s interesting to see how the Composition API is used in Vue 2. One of its key advantages I’ve observed is the handling of methods, and component state is made more accessible and also its reactivity.

I hope you learned a few things about Vue. Hit me up on Twitter if you have any questions or feedback.

And feel free to add new features to the app, as this is a great way to learn. You can check out the source code here.