VueJS components

Important to use a prefix liek the company name so that your component is unique

In the root Vue instance data can be an object

In component data should be a function, so that we avoid having objects data pointing to the same place in memory.

Methods can be an object, as the functions will only run in the component context

Component example

    <div id="app">
        <my-component></my-component>
    </div>
    <script>

    Vue.component('my-component',
    {
        data: function(){
            return {
                status: 'Critical'
            }
        },
        template: '<p>Server Status: </p>'
    });

    new Vue({
    el: '#app',
    })
    </script>

Store component as a variable

Remove selector

    var cmp = {
        data: function(){
            status: 'Critical'
        }
    }

Then register the component locally on the vue instnace:

    new Vue(({
        el: '#app',
        components: {
            'my-cmp': cmp
        }
    }))      

Methods in components

In components you can write methods like this:

    methods: {
        changeStatus() {
            
        }
    }

Importing your component

    import Home from './Home.vue'

    //Globally add component
    //Allows to add <app-server-status> element in component template
    Vue.component('app-server-status', Home);

Template code

Wrap all your template code into one element

Vue component Naming Convention

CapitalCase: ServerStatus.vue

Styles

By default any item in style tag is set globally.

To override this add scoped: uses shadow DOM

<style scoped>///</style>

Communicating between components

Use props property set from the parent

Create a props variable of the components Vue Instance:

    export default {
        props: ['name']
    }

Send it to the component with

    <app-user-detail :name="name"></app-user-detail>

If you just want to send the plain text and not the variable use:

    <app-user-detail name="name"></app-user-detail>

Can access these props like a normal property set up in the data property

Validating Props

    props: {
        name : String
    }

    props: {
        name : {
            type: String,
            required: true
        }
    }

    props: {
        name : {
            type: String,
            default: 'Stephen'
        }
    }

If type is object then the default should be a function which returns an object

    props: {
        name : {
            type: Object,
            default: function(){
                return {name: 'Max'}
            }
        }
    }

Types

Objects and arrays are reference types and only exist in memory once

Variables only store the pointer

Therefore changing in the child component, you also change in the parent component

Sometimes you need to inform the parent component that it did indeed change:

    this.$emit('<eventName>', variable);

    this.$emit('nameWasReset', this.name);

Then you have to lsiten for the event on the component:

    <myComponent @nameWasReset="name = $event"

Unidirection information

Can communiate from parent to child and child to parent, but not from child to child.

Event Bus

General centralised code

In ‘main.js’

    export const eventBus = new Vue();

In component

    import { eventBus} from '../main';

    eventBus.$emit('ageWasEdited', this.userAge);

Eventbus must be created before the view instance

In created lifecycle event:

    created(){
        eventBus.$on('ageWasEdited', (age) => {
            this.userAge = age;
        });
    }

Slots

Slots allow us to reserve a space in a compnents template to output html content within that component

In parent:

    <appQuote>
            <h2>The Quote</h2>
            <p>A wonderful quote!</p>
    </appQuote>  

In component:

    <template>
        <div>
            <slot></slot>
        </div>
    </template>

Remember: The styling of the child applies. Everything else works as normal on parent.

Named Slots

You can name slots to slectively display content:

    <appQuote>
            <h2 slot="title"></h2>
            <p slot="content">A wonderful quote!</p>
    </appQuote>  

    <div class="title">
        <slot name="title"></slot>
    </div>
    <hr/>
    <div>
        <slot name="content"></slot>
    </div>

Unnamed Slots

Unnamed slots will become the default slot

Dynamic Components

Selectively add components to the DOM

    <component :is="selectedComponent">
        <p>Default content</p>
    </component>

Note: The component is destroyed and recreate when switched

Good use case is a slideshow, let use put in content.

Keep Alive

Preserve state, but now destroyed() lifecycle hook is not used.

    <keep-alive>
        <component :is="selectedComponent">
            <p>Default content</p>
        </component>
    </keep-alive>

Lifecycle hooks

deactivated ()and activated()

Native event modifier

    @click.native

Treat the click as if it was on the component not the underlying returned template