Episode 2 of 8

A Simple Vue App

Build a simple Vue app without Vuex first — see the limitations of props and events, setting the stage for centralized state management.

A Simple Vue App

Before adding Vuex, let us build a simple app without it to understand the pain points it solves. We will create a product list with a counter that tracks how many items have been viewed.

Project Setup

vue create vuex-playlist
cd vuex-playlist
npm run serve

The App Structure

App.vue
├── ProductList.vue   (list of products)
└── Sidebar.vue       (shows total count)

App.vue (Parent)

<template>
    <div id="app">
        <h1>Product App</h1>
        <div class="layout">
            <product-list :products="products" @viewed="incrementViewed"></product-list>
            <sidebar :totalViewed="totalViewed"></sidebar>
        </div>
    </div>
</template>

<script>
import ProductList from './components/ProductList.vue';
import Sidebar from './components/Sidebar.vue';

export default {
    components: { ProductList, Sidebar },
    data() {
        return {
            products: [
                { id: 1, name: 'Banana Skin', price: 20 },
                { id: 2, name: 'Shiny Star', price: 40 },
                { id: 3, name: 'Green Shells', price: 60 },
                { id: 4, name: 'Red Shells', price: 80 },
                { id: 5, name: 'Mushroom', price: 15 }
            ],
            totalViewed: 0
        };
    },
    methods: {
        incrementViewed() {
            this.totalViewed++;
        }
    }
};
</script>

ProductList.vue (Child)

<template>
    <div class="product-list">
        <div v-for="product in products" :key="product.id" class="product">
            <span>{{ product.name }} — ${{ product.price }}</span>
            <button @click="$emit('viewed')">View</button>
        </div>
    </div>
</template>

<script>
export default {
    props: ['products']
};
</script>

Sidebar.vue (Child)

<template>
    <div class="sidebar">
        <h3>Summary</h3>
        <p>Total viewed: {{ totalViewed }}</p>
    </div>
</template>

<script>
export default {
    props: ['totalViewed']
};
</script>

The Problem

This works for a small app, but notice how App.vue is the middleman — it holds products and totalViewed just to pass them to children. If we add more components that need this data, the parent keeps growing. Props cascade down, events bubble up, and it becomes difficult to track where data is changed.

Key Takeaways

  • In a simple app, the parent holds shared data and passes it down via props
  • Child components communicate upward via events
  • The parent becomes a "state manager" — not its real job
  • As the app grows, this pattern becomes increasingly hard to maintain
  • Vuex removes the middleman by putting shared state in a central store