Debouncing issue in Vuejs 2 when using watch option

After adding a debounce function in VueJs, I noticed that it works perfectly when passing the number of milliseconds directly. However, if I use a reference to a prop, it seems to be ignored.

Here's a summary of the props:

props : {
    debounce : {
        type : Number,
        default : 500
    }
}

Below is the watch option causing issues:

watch : {
    term : _.debounce(function () {
        console.log('Debounced term: ' + this.term);
    }, this.debounce)
}

And here is an alternative watch option that works without any problems:

watch : {
    term : _.debounce(function () {
        console.log('Debounced term: ' + this.term);
    }, 500)
}

I have a feeling that it could be related to a scope problem, but I'm uncertain about how to resolve it. When I modify the watch method as shown below:

watch : {
    term : function () {
        console.log(this.debounce);
    }
}

I can see the correct debounce value (500) displaying in the console.

Answer №1

One way to enhance @Bert's solution is by constructing the watcher's function within the created() method.

// Check out this Vuejs 2 example on debounce functionality with watch option

console.clear()

Vue.component("debounce",{
  props : {
    debounce : {
      type : Number,
      default : 500
    }
  },
  template:`
    <div>
      <input type="text" v-model="term">
    </div>
  `,
  data(){
    return {
      term: "",
      debounceFn: null
    }
  },
  created() {
    this.debounceFn = _.debounce( () => {
      console.log('Debounced term: ' + this.term);
    }, this.debounce)
  },
  watch : {
    term : function () {
      this.debounceFn();
    }
  },
})

new Vue({
  el: "#app"
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<div id="app">
  <debounce :debounce="2000"></debounce>
</div>

Discover this code snippet live on CodePen

Answer №2

The main issue at hand revolves around the usage of this.debounce as the interval when defining the debounced function. When _.debounce(...) is executed (during the compilation of the component), the function is not yet linked to Vue, resulting in this not referencing Vue and thus this.debounce being undefined. To rectify this, it's essential to set up the watch after the component instance is created. Vue offers a solution for this through the utilization of $watch.

My recommendation would be to implement this within the created lifecycle hook.

created(){
  this.unwatch = this.$watch('term', _.debounce((newVal) => {
     console.log('Debounced term: ' + this.term);
  }, this.debounce))
},
beforeDestroy(){
  this.unwatch()
}

Note that the code also contains a call to unwatch before the destruction of the component. While Vue typically manages this process automatically, manually adding the watch requires manual removal as well. Naturally, unwatch needs to be included as a data property.

Below is an illustration of how this works in action.

console.clear()

Vue.component("debounce",{
  props : {
    debounce : {
      type : Number,
      default : 500
    }
  },
  template:`
    <input type="text" v-model="term">
  `,
  data(){
    return {
      unwatch: null,
      term: ""
    }
  },
  created(){
    this.unwatch = this.$watch('term', _.debounce((newVal) => {
      console.log('Debounced term: ' + this.term);
    }, this.debounce))
  },
  beforeDestroy(){
    this.unwatch()
  }
})

new Vue({
  el: "#app"
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c7b1b2a287f5e9f3e9f5">[email protected]</a>"></script>
<div id="app">
  <debounce :debounce="250"></debounce>
</div>

Answer №3

To ensure that the debounced method is consistently called every time the watch is triggered, it needs to be abstracted. If we embed the debounced function within a Vue computed or watch property, it will reset on each trigger event.

const debouncedGetData = _.debounce(getData, 1000);

function getData(val){
  this.newFoo = val;
}

new Vue({
  el: "#app",
  template: `
    <div>
      <input v-model="foo" placeholder="Type something..." />
      <pre>{{ newFoo }}</pre>
    </div>
`,
    data(){
      return {
        foo: '',
        newFoo: ''
      }
    },
    watch:{
      foo(val, prevVal){
        debouncedGetData.call(this, val);
      }
    }
  
  })
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="app"></div>

Best of luck...

Answer №4

Setting up a new Vue instance with debounce functionality for handling user input:
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.js"></script>
<div id="term">
  <input v-model="term">
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Every time I attempt to run "npm install" on Visual Studio Code, I encounter an error

Every time I try to run npm install, I encounter this error. My node version is 18.9.1 and I have exhausted all possible solutions. Any help would be greatly appreciated. '''npm ERR! code ENOENT npm ERR! syscall open npm ERR! path C:\Us ...

Encountering an "Unknown Provider" issue while trying to inject a provider from another module into a

Having trouble with two modules, module A and module B, that are interdependent. Module A is currently in the process of being bootstrapped. I need to inject a provider from module A into the config block of module B. Unfortunately, I keep getting an erro ...

The arrow icon for selecting input in Material Dashboard React is missing

Source Code View Result Why is the arrow icon not visible when viewing the select like this? I am using "@mui/material": "^5.8.6". Can someone please help me with this? <Box sx={{ width: "auto" }}> <FormControl fullWidth> ...

Maximizing the Efficiency of jQuery and Javascript Frameworks

Currently, I am working on a project that involves utilizing a JavaScript framework (jQuery) in conjunction with various plugins (validation, jquery-ui, datepicker, facebox, and more) to enhance the functionality of a modern web application. However, I ha ...

The functionality of the Node.js/Express.js app is limited to operating solely on Port 3000

I'm currently troubleshooting an issue with my Node.js/Express.js app running on my server. It seems to only work on port 3000, and I'm trying to understand why. Here's what I've discovered: When I don't specify a port (app.liste ...

What is your approach to converting this jQuery code to ES6 syntax?

The concept involves gathering all the links and corresponding IDs, and hiding inactive content. When a link is clicked, the associated content should be displayed. The Structure <div class="navbar"> <nav> <ul class="navTabs"> ...

Merging two arrays that have identical structures

I am working on a new feature that involves extracting blacklist terms from a JSON file using a service. @Injectable() export class BlacklistService { private readonly BLACKLIST_FOLDER = './assets/data/web-blacklist'; private readonly blackl ...

Control the line height in DataTables

Is there a way to adjust the line height for a tr using either DataTables settings or CSS? I've attempted different methods, but nothing seems to change the line-height. https://i.sstatic.net/GwFaD.png Table CSS ...

Top tips for data manipulation

I am facing an issue with my JavaScript code that makes an ajax request to the server and receives JSON data, which is not correctly formatted for array-based manipulation. A colleague suggested a client-side solution to convert object-based JSON into arra ...

Modify the text tone within a specific cell

Welcome to my unique webpage where I have implemented a special feature. The text highlighted in red represents the unique identifier for each individual cell. Interestingly, below there is an input field containing the code "0099CC", which corresponds to ...

Creating a vertical slider with an unordered list

Looking to create a vertical menu with a fixed height that smoothly slides up and down when the arrow buttons are clicked. I'm struggling to figure out how to properly use offsets to determine where to navigate to. Right now, I am using the relative ...

Encountering an error while trying to install the VUE CLI using the npm command with the message "

I'm currently using PC/Windows 10 with Node.js version 15.0.0 and npm 6.14.8. While trying to set up Vue CLI, I encountered an error message. Despite having the latest Node.js version installed, my attempts to resolve the issue by running commands l ...

Issue with window resize directive not functioning as expected

I have recently crafted a personalized directive in AngularJS. Here's the code snippet: var esscom = angular.module('esscom',['ngMaterial' ,'ngMessages','ui.bootstrap','ui.router']); esscom.directiv ...

Synchronize information between mongoDB and firebase bidirectionally

My current situation: Having developed an application using React, NodeJS, and Electron, most of my users utilize the app offline. Next plans: With intentions to cater to mobile users as well, I am considering creating a mobile application using React-N ...

Standardize all values for each key in sub-dictionaries and include them as additional key-value pairs

Suppose there is a dictionary containing nested sub-dictionaries: let dict = { "SEATTLE" : { "gross_sales" : 106766, "price" : 584.50, "dates" : [ { " ...

Verify if a string containing only numerical values contains any non-numeric characters

I have an input field for a phone number, but the type is set to text instead of number. I want to validate it if there are any non-numeric characters present, since I have formatted the input to look like this: 123-123-1234 Here is my input: <input (ke ...

Changing the formatting of a buffer from int8 to float32 using JavaScript

Within a buffer, I have a series of bytes that were read from a file. I am looking to convert these bytes into a sequence of float32 values without having to copy them to a new buffer, given that each data block is approximately 15KB in size. I have come a ...

Oops! We encountered an issue with this dependency being missing - TypeScript and Vue

Just starting out with TS and Vue. Encountering this error message while attempting to run vue-cli-service serve: This dependency was not found: * @store in ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/ts-loader??ref--12-1!./node_ ...

Utilizing Array Filters and State in React JS to Conceal Table Columns

I am currently working on converting this code into a functional component, but I am facing issues with the behavior of my arrays. EXPECTED OUTPUT: https://stackblitz.com/edit/antd-showhidecolumns Here is my modified version using functional components: ...

Can you provide instructions on executing package dependencies using yarn in the command line? For example, is there a command similar to npx tsc init for initializing a npm

When utilizing yarn, the node_modules folder is not present. Instead, dependencies are stored in a .yarn/cache folder. I attempted to use yarn dlx tsc init and npx tsc init, but they did not achieve the desired result. There are various development depend ...