DEV Community

Valentin Prugnaud 🦊
Valentin Prugnaud 🦊

Posted on

Custom v-model with Vue.js: Update

A while back, in 2019, I wrote an article demonstrating how to create a custom Vue component, and handle the v-model capabilities:

https://dev.to/valentinprgnd/wrap-a-text-field-in-a-component-with-vue-js-gak

I recently discovered an alternative way to do it, which does not require a watcher, thus making the code much faster and less resource heavy.

The original post suggested this method:

<template>
  <div class="custom-input">
    <input v-model="localValue" placeholder="Enter your name">
  </div>
</template>

<script>
export default {
  name: "TextField",
  props: {
    value: String // 1. Receives the value as a prop
  },
  data() {
    return {
      localValue: ""
    };
  },
  created() {
    this.localValue = this.value; // 2. Copy the value in a local value variable

    // Set a watcher to emit the changes to the parent component
    this.$watch("localValue", value => {
      this.$emit("input", value);
    });
  }
};
</script>
Enter fullscreen mode Exit fullscreen mode

While functional, the use of a watcher here can be really resource heavy (particularly if you create a lot of such components).

A better approach would be to use a computed property, like so:

<template>
  <div class="custom-input">
    <input v-model="localValue" placeholder="Enter your name">
  </div>
</template>

<script>
export default {
  name: "TextField",
  props: {
    value: String // 1. Receives the value as a prop
  },
  computed: {
    localValue: {
      get() {
        return this.value;
      },
      set(value) {
        this.$emit('input', value);
      }
  }
};
</script>
Enter fullscreen mode Exit fullscreen mode

Not only it reduces the boilerplate code, but it also avoids the use of a watcher, making your component faster and less resource heavy 🎉

Oldest comments (0)