Vue 3 is the latest version of the easy to use Vue JavaScript framework that lets us create front end apps.
In this article, we’ll look at how to create a shopping cart app with Vue 3 and JavaScript.
Create the Project
We can create the Vue project with Vue CLI.
To install it, we run:
npm install -g @vue/cli
with NPM or:
yarn global add @vue/cli
with Yarn.
Then we run:
vue create shopping-cart
and select all the default options to create the project.
We also need the Vue Router package to let us navigate to different pages in the app.
To do this, we run:
npm i vue-router@next
Create the Shopping Cart
The first step for creating the shopping cart is to create the view files.
We create the views
folder in the src
folder.
Then inside it, we add the Cart.vue
and Store.vue
files to create the store page which we can browser.
Cart.vue
has the cart page.
Then in main.js
, we add the Vue Router into our app by writing:
main.js
import { createApp } from "vue";
import App from "./App.vue";
import Cart from "./views/Cart";
import Store from "./views/Store";
import { createRouter, createWebHashHistory } from "vue-router";
const routes = [
{ path: "/", component: Store },
{ path: "/cart", component: Cart }
];
const router = createRouter({
history: createWebHashHistory(),
routes
});
const app = createApp(App);
app.use(router);
app.mount("#app");
We import the view component files we created earlier.
Then we add them to the routes
array.
Next, we call createRouter
to create the router object.
We add the routes
object, we created earlier inside the argument object.
createWebHashHistory
makes Vue Router add a #
sign between the first segment and the other segments of the URL.
And then we call app.use
with router
to add the router.
To create a simple store page, we go into Store.vue
and write:
<template>
<div>
<h1>Store</h1>
<div v-for="item of items" :key="item.id">
<p>{{ item.name }}</p>
<img :src="item.imageUrl" />
<button @click="removeFromCart(item.id)" v-if="isInCart(item.id)">
remove from cart
</button>
<button @click="addToCart(item.id)" v-else>add to cart</button>
</div>
<button @click="$router.push('/cart')">check out</button>
</div>
</template>
<script>
const items = Object.freeze([
{
id: 1,
imageUrl: "grape.jpg",
name: "grape",
},
{
id: 2,
imageUrl: "orange.jpg",
name: "orange",
},
{
id: 3,
imageUrl: "apple.jpg",
name: "apple",
},
]);
export default {
name: "Store",
data() {
return {
items,
cart: [],
};
},
methods: {
isInCart(itemId) {
if (!localStorage.getItem("cart")) {
localStorage.setItem("cart", JSON.stringify([]));
}
const cartItem = this.cart.find(({ id }) => id === itemId);
return Boolean(cartItem);
},
addToCart(itemId) {
const item = this.items.find(({ id }) => id === itemId);
if (!localStorage.getItem("cart")) {
localStorage.setItem("cart", JSON.stringify([]));
}
const cartItems = JSON.parse(localStorage.getItem("cart"));
cartItems.push(item);
localStorage.setItem("cart", JSON.stringify(cartItems));
this.cart = JSON.parse(localStorage.getItem("cart"));
},
removeFromCart(itemId) {
const cartItems = JSON.parse(localStorage.getItem("cart"));
const index = cartItems.findIndex(({ id }) => id === itemId);
cartItems.splice(index, 1);
localStorage.setItem("cart", JSON.stringify(cartItems));
this.cart = JSON.parse(localStorage.getItem("cart"));
},
},
};
</script>
We render the store items with v-for
.
We display the remove from cart button if the item is already added top the cart.
And we show the add to cart button otherwise.
The check is done by the isInCart
method, which gets the cart items from the this.cart
reactive property and check if find
returns anything given the itemId
.
addToCart
adds the item to the cart
entry in local storage, which is an array that we create if it doesn’t exist.
After that, we update the this.cart
reactive property with the latest value from local storage.
removeFromCart
finds the index from the cart
items from local storage by the itemId
with findIndex
.
Then we call splice
to remove the item by the index
.
And then we call setItem
to update the cart with the latest items in the cart.
And we update this.cart
with the latest values form local storage.
items
have the store items.
The checkout button calls $router.push
with '/cart'
to go the cart page.
To add the content for the cart page, we write the following in Cart.vue
:
Cart.vue
<template>
<div>
<h1>Cart</h1>
<div v-for="(c, index) of cart" :key="c.id">
<p>{{ c.name }}</p>
<img :src="c.imageUrl" />
<button @click="removeFromCart(index)">remove from cart</button>
</div>
</div>
</template>
<script>
export default {
name: "Cart",
data() {
return {
cart: [],
};
},
methods: {
removeFromCart(itemId) {
const cartItems = JSON.parse(localStorage.getItem("cart"));
const index = cartItems.findIndex(({ id }) => id === itemId);
cartItems.splice(index, 1);
localStorage.setItem("cart", JSON.stringify(cartItems));
this.cart = JSON.parse(localStorage.getItem("cart"));
},
getCart() {
if (!localStorage.getItem("cart")) {
localStorage.setItem("cart", JSON.stringify([]));
}
this.cart = JSON.parse(localStorage.getItem("cart"));
},
},
beforeMount() {
this.getCart();
},
};
</script>
We have the same remvoeFromCart
method as in Store.vue
.
getCart
gets the cart
item from local storage and then set the returned value as the value of the this.cart
reactive property.
And then we render the this.cart
entries with v-for
in the template.
We have the remove from cart button to remove the item with removeFromCart
.
Finally, in App.vue
, we write:
<template>
<div>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "App",
};
</script>
<style>
img {
width: 200px;
height: 200px;
}
</style>
to add the router-view
so we can see the route that Vue Router renders.
We also shrink the images to 200px by 200px with the style
tag.
Conclusion
We can create a simple shopping cart easily with Vue 3 and JavaScript.