WTFranklin
WTFranklin

Reputation: 2568

Uncaught TypeError exports is read-only

I'm working through the vue bootcamp from Scrimba right now and I can't seem to get the event bus working for communicating between components. I get this error when going to my page

Uncaught TypeError: "exports" is read-only

Following along exactly like the video, even copying and pasting their code gives me this error. I'm on a slightly newer version of Vue than they are using. I'm using version 2.6.11.

In the video I'm watching, he uses

import Vue from 'vue';

module.exports = new Vue();

I have also tried other variations that I've found online, including

import Vue from 'vue';

export const EventBus = new Vue();

and others that I have found online, but I get the same error every time. I've seen multiple tutorials online that have versions that work for them, but I get the same error every time. I'm at a loss as to how to fix this at this point since I have actually copy and pasted the examples and can't get this to work properly. I can't tell if there's something really easy I'm missing or something that's not so obvious, but I've been going in circles for about an hour and half and can't figure it out.

Here are the components I'm trying to use the event bus in:

Product.vue

<template>
    <div class="product-wrapper">
        <div class="product-image">
            <img :src="product.image">
        </div>
        <div class="product-name">{{ product.name }}</div>
        <div class="product-price">{{ priceFormatted }}</div>
        <div><button @click.prevent="addProduct">ADD</button></div>
    </div>
</template>

<script>
    import EventBus from '../bus'

    module.exports = {
        props: {
            product: Object
        },
        
        computed: {
            priceFormatted: function () {
                return '$' + this.product.price / 100;
            }
        },

        methods: {
            addProduct: function() {
                EventBus.$emit('add-product', this.product);
            }
        }
    }
</script>

<style scoped>
    .product-wrapper {
        display: flex;
        align-items: center;
        justify-content: space-between;
        width: 100%;
        padding-bottom: 15px;
        border-bottom: 1px solid #eee;
        margin-bottom: 15px;
    }
    .product-image,
    .product-name,
    .product-price {
        margin: 0 10px;
    }
    img {
        width: 100px;
        height: 100px;
        object-fit: cover;
        border-radius: 9999px;
        border: 3px solid #fff;
    }
    button {
        background-color: #222;
        color: #eee;
        padding: 5px 10px;
        border-radius: 15px;
        margin-right: 15px;
    }
</style>

Cart.vue

<template>
    <div>
        <div>
            <ul>
                <li class="price-row">
                    <div>Old Red Friend</div>
                    <div class="quantity-row">
                        <div class="price-quantity">Qty: 2</div>
                        <div>$29.97</div>
                    </div>
                </li>
            </ul>
        </div>
        
        <div class="price-row">
            <div class="price-label">Sub-total</div>
            <div class="price-wrapper">$9.99</div>
        </div>
        <div class="price-row">
            <div class="price-label">Shipping</div>
            <div class="price-wrapper">$9.99</div>
        </div>
        <div class="price-row">
            <div class="price-label">Total</div>
            <div class="price-wrapper">$9.99</div>
        </div>
        <button class="checkout-button">CHECKOUT</button>
    </div>
</template>

<script>
    import EventBus from '../bus.js'

    module.exports = {
        data: function() {
            EventBus.$on('add-product', product => {
                this.addProduct(product);
            });

            return {
                products: []
            }
        },
        methods: {
            addProduct: function(product) {
                this.products.push(product);

                console.log(this.products);
            }
        }
    }
</script>

<style scoped>
    .quantity-row {
        display: flex;
    }
    .price-quantity {
        margin-right: 15px;
    }
    .checkout-button {
        width: 100%;
        text-align: center;
        padding: 10px 0;
        background: #000;
        color: #eee;
    }
    .price-row {
        display: flex;
        justify-content: space-between;
        border-bottom: 1px solid #eee;
        margin: 10px;
        padding-bottom: 10px;
    }
</style>

EDIT: Here is the error output I get in the console enter image description here

Upvotes: 1

Views: 988

Answers (1)

Majed Badawi
Majed Badawi

Reputation: 28424

The components need to be exported as follows export default {}.

For the event bus, you can do this:

import Vue from 'vue';
export const EventBus = new Vue();
import { EventBus } from '../bus.js';

Or this:

import Vue from 'vue';
export default new Vue();  
import EventBus from '../bus.js';

Upvotes: 1

Related Questions