post

Writing your own components in VueJS is going to change the way you organize your code, your thought process.

Beginners might feel a bit hesitant to write their own components. Also, if you ever faced an error like follows:

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value.

You might be using props the wrong way! Have you thought of using v-model?

Let's write the simplest of all components, a text input box.

ParentComponent.vue (With input tag)

<template>
    <div>
        <input type="email" v-model="email">
    </div>
<template>

<script>
    export default {
        data () {
            return {
                email: ''
            };
        },
    }
</script>

The above script would let you capture email typed by user into data model email.

But what if you want to use a component instead of HTML input tag.

ParentComponent.vue (With Text Input Custom Component)

<template>
    <div>
        <email-input v-model="email"></email-input>
    </div>
<template>

<script>
    import EmailInput from './EmailInput.vue'

    export default {
          components:{
            EmailInput
        },
        data () {
            return {
                email: ''
            };
        },
    }
</script>

EmailInput.vue (Custom Component)

<template>
    <input
        v-bind:value="value"
        v-on:input="$emit('input', $event.target.value)"
    >
<template>

<script>
    export default {
        props : ['value'],
        data () {
            return {
                email: ''
            };
        },
    }
</script>

This concept is documented at https://vuejs.org/v2/guide/components.html#Using-v-model-on-Components

  • The value of v-model is passed as prop value to the component.
  • input event is fired to which vueJS responds and value is stored into email data model in ParentComponent

You can change the above component to accept any type of text input.

TextInput.vue (Custom Component)

<template>
    <input
        :type="type"
        v-bind:value="value"
        v-on:input="$emit('input', $event.target.value)"
    >
<template>

<script>
    export default {
        props : ['value','type'],
        data () {
            return {
                email: ''
            };
        },
    }
</script>