Before we get started make sure your Laravel project has something like "vue": "^2.1.10" in the devDependencies section of your package.json file (you might have a different version than 2.1.10). After that run npm run install in your terminal inside the root folder of your project if you haven't done this yet.

The View

To start let's place our future Vue component into a view. Open your main layout file (resources/views/layouts/app.blade.php or whatever you have) and add a new element somewhere at the top of the <div id="app">. We'll call our component notification.

<notification></notification>

We're going to expand this as we need to check if anything was flashed from a controller. We'll pass the flashed message and its type to the component via properties. status is what flashed by Laravel's authentication system, but I wanted to flash my messages under a different session key, hence the double condition. As for the type we'll simply be passing a bootstrap alert class.

@if (session('notification'))
    <notification type="{{ session('notificationType') }}" message="{{ session('notification') }}"></notification>
@elseif (session('status'))
    <notification type="alert-primary" message="{{ session('status') }}"></notification>
@else
    <notification></notification>
@endif

The Component

Now let's create the Vue component file in the resources/assets/js/components folder. We'll call it Notification.vue. Then register the component as a global component in the resources/assets/js/app.js file.

Vue.component('notification', require('./components/Notification.vue'));

Open the component file and add this boilerplate code:

<template>
</template>

<style>
</style>

<script>
    export default {

    }
</script>

Now we can start building it up. Every Vue template must have a single parent element. We'll also use that element for positioning of our notification. The div inside is the actual notification element.

<template>
    <div class="notification-wrapper">
        <div class="notification alert alert-primary">
            Some random notification
        </div>
    </div>
</template>

At his point you can run npm run dev in your terminal to compile the component. Then go to any page of your website and make sure you see the text Some random notification at the top of the page. Now let's apply some css. Edit the <style> block like this:

<style>
.notification-wrapper {
    position: fixed;
    left: 50%;
    top: 2rem;
    z-index: 10000;
}

.notification {
    position: relative;
    left: -50%;
}
</style>

This will put our notification at the top of the screen centering it horizontally. I set a random big number for the z-index so that it always shows on top of everything else.

Let's move on to the functionality. We're passing two properties to our component. Let's accept them. We're going to work within the <script> block now.

<script>
    export default {
        props: ['type', 'message']
    }
</script>

Below the props we're going to form the data object. Don't forget to add a comma after the props array.

data() {
    return {
        show: false,
        notification: this.message,
        alertClass: this.type,
        hideTimeout: false
    }
}

The show property will control the visibility of the notification. By default it will be hidden. hideTimeout will be used for hiding the notification after a few seconds.

Now let's go back to our template and bind the data. This is what the template should look like now:

<div class="notification-wrapper">
    <div :class="'notification alert ' + alertClass"
        v-show="show"
        v-text="notification"></div>
</div>

The "v-show" attribute controls an element's visibility and displays it only when the variable bound to it returns true.

Now we need to display the notification after the component has been created if any default data has been passed to it (if a message has been flashed by a controller). Add this to our script:

created () {
    if (this.notification) {
        this.showNotification();
    }
},

methods: {
    showNotification() {
        this.show = true;
    }
}

In order to display the notification we just need to set this.show to true. I'd also like to automatically hide the notification, say, after 5 seconds. In order to do this we just need to set a timeout which will set this.show to false after 5 seconds. Make these changes to the methods:

showNotification() {
    this.show = true;
    this.hideNotification();
},

hideNotification() {
    this.hideTimeout = setTimeout(() => {
        this.show = false;
    }, 5000);
}

We're saving the timeout in a variable for a reason. Sometimes you don't want to wait for the whole 5 seconds and want to close the notification right away. We're going to add another method for that right after the hideNotification() method.

destroyNotification() {
    this.show = false;
    clearTimeout(this.hideTimeout);
}

We need to clear the timeout so that if another notification is being showed shortly after the last one, the new one stays visible for the full 5 seconds. Now we just need to bind this function to the click event of our notifications. Modify the template like this:

<div :class="'notification alert ' + alertClass"
    v-show="show"
    v-text="notification"
    @click="destroyNotification"></div>

We're done with the main part of development. If you want to flash a message from a controller just attach this to your response:

->with('notification', 'Data has been saved successfully!') // The message
->with('notificationType', 'alert-success'); // A Bootstrap alert class

Notifications From JavaScript

Finally, you'd probably want to display these notifications dynamically by calling a JavaScript method. To achieve this you should do the following. Open resources/assets/js/bootstrap.js and at the very bottom add:

window.Vue = require('vue');

window.events = new Vue();

window.showNotification = function(message, type = 'alert-primary') {
    window.events.$emit('showNotification', message, type);
}

Here we've created a global JS function that emits a global Vue event. We pass a message and a notification type with this event. Type equals to alert-primary by default, so we don't have to pass it every the time.

We'll listen for this event inside our component. Set a listener within the created() method:

window.events.$on('showNotification', (message, type) => {
    this.notification = message;
    this.alertClass = type;
    this.showNotification();
});

Now you can call this method from anywhere in your JavaScript whenever you want to show a notification.

showNotification('Oops! Something went wrong...', 'alert-danger');

Complete Code

resource/views/layouts/app.blade.php (or whatever is your main layout file)

...
<body>
    <div id="app">
        @if (session('notification'))
            <notification type="{{ session('notificationType') }}" message="{{ session('notification') }}"></notification>
        @elseif (session('status'))
            <notification type="alert-primary" message="{{ session('status') }}"></notification>
        @else
            <notification></notification>
        @endif

        ...
    </div>
</body>
...

resources/assets/js/app.js

require('./bootstrap');

window.Vue = require('vue');

Vue.component('notification', require('./components/Notification.vue'));

const app = new Vue({
    el: '#app'
});

resources/assets/js/bootstrap.js

window.Vue = require('vue');

window.events = new Vue();

window.showNotification = function(message, type = 'alert-primary') {
    window.events.$emit('showNotification', message, type);
}

resources/assets/js/components/Notification.vue

<template>
    <div class="notification-wrapper">
        <div :class="'notification alert ' + alertClass"
            v-show="show"
            v-text="notification"
            @click="destroyNotification"></div>
    </div>
</template>

<style>
.notification-wrapper {
    position: fixed;
    left: 50%;
    top: 2rem;
    z-index: 10000;
}

.notification {
    position: relative;
    left: -50%;
}
</style>

<script>
    export default {
        props: ['type', 'message'],

        data() {
            return {
                show: false,
                notification: this.message,
                alertClass: this.type,
                hideTimeout: false
            }
        },

        created () {
            if (this.notification) {
                this.showNotification();
            }

            window.events.$on('showNotification', (message, type) => {
                this.notification = message;
                this.alertClass = type;
                this.showNotification();
            });
        },

        methods: {
            showNotification() {
                this.show = true;
                this.hideNotification();
            },

            hideNotification() {
                this.hideTimeout = setTimeout(() => {
                    this.show = false;
                }, 5000);
            },

            destroyNotification() {
                this.show = false;
                clearTimeout(this.hideTimeout);
            }
        }
    }
</script>