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 🎉

Top comments (0)