How can I prevent a method called by a Vue component from running every time the v-model changes?

RSF

I have a form that populates a number dropdown lists from an API, so I created a method that gets the list (getList()) from that API. The dropdowns are built using the Vuetify v-autocomplete component, which populate the list using the items prop and I am calling getList() from this prop.

My problem is that all of the questions share a v-model object to store the responses and every time the v-model changes, all of the autocompletes call the getList() method again to repopulate the lists. Since I have multiple questions and each is making an API call multiple times, this form is running quite slowly.

Here's an example of this:

<template>
  <v-app>
    <v-container>
      <v-text-field label="text question" v-model="responses.text"></v-text-field>
      <v-autocomplete
        label="random question"
        :items="getList()"
        v-model="responses.autocomplete"
      ></v-autocomplete>

      <p>Text v-model: {{ responses.text }}</p>
      <p>Autocomplete v-model: {{responses.autocomplete}}</p>
    </v-container>
  </v-app>
</template>

<script>
  export default {
    data() {
      return {
        responses: {},
      }
    },

    methods: {
      getList() {
        console.log('Getting list')
        return ['value1', 'value2', 'value3']
      },
    },
  }
</script>

Note that every time you add a new character to the text field, the getList() method is called (check the console).

My question is, is there a way to prevent the getList() method from getting called every time the v-model changes?

What I've tried:

  • Giving each question its own v-model so they don't affect each other. Unfortunately this doesn't work. It looks like any time any of the data changes, the getList() method is called. See this other example:
<template>
  <v-app>
    <v-container>
      <v-text-field label="text question" v-model="text"></v-text-field>
      <v-autocomplete
        label="random question"
        :items="getList()"
        v-model="autocomplete"
      ></v-autocomplete>

      <p>Text v-model: {{ text }}</p>
      <p>Autocomplete v-model: {{autocomplete}}</p>
    </v-container>
  </v-app>
</template>

<script>
  export default {
    data() {
      return {
        responses: {},
        text: '',
        autocomplete: '',
      }
    },

    methods: {
      getList() {
        console.log('Getting list')
        return ['value1', 'value2', 'value3']
      },
    },
  }
</script>
  • Getting the lists in the mounted hook. While this solves this problem, I cannot use it in my case because the dropdown list of some questions are dependent on other questions. For example, if Question 1 gets a response of A, Question 2 will get list [x, y, z], but if the response is B, it will get list [q, r, s]. So I do need Question 2 to react to Qestion 1, but I don't need it to react to Question 3.

So yes, any tips on improving the performance of this component by calling getList only when it's actually needed?

Moritz Ringler

As you already did, store the current list items in data, but instead of setting it in mounted, updated it through a watcher.

    watch: {
      'responses.text': {
        handler(current, old) {
          if (!this.needsReload(current, old)){
            return
          }
          this.listItems = this.getList(current)
        },
        immediate: true,
      },
    },

Setting the immediate:true flag will trigger an initial load when the watcher is set up.

In your example, you could use a computed, since getList() is synchronous, but when you call an API, you should stick to a watcher since computeds should be free of side-effects.

Here is the updated playground, where the list is filled according to the first letter in the text input.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How can I prevent Backbones save method from trying to update every model?

Angular - How to prevent ngIf from destroying the component every time the condition changes

How can I update computed from method in vue component?

How can I calculate running time for model

How to prevent a method from being called all the time

How can I prevent Django view from being called repeatedly despite of long execution time?

How can I prevent Ask.com Toolbar from being installed every time Java is updated?

How can I prevent Windows 10 from corrupting the ext4 superblock every time?

how i can save changes in the document without closing it every time

How can I use v-model with a functional template component in Vue?

How can I prevent multiple calls from an event listener in a Vue Js Component?

how can I reference a method from the same component in the data of the component vue js

How can I scroll by 100 vh every component in vue?

How can I prevent my custom directive from getting compiled/executed every time I use $route.reload()

How can I prevent Windows 8.1 from reinstalling Metro applications automatically every time I create a new local user account?

Prevent upvote model from being called for every comment

How can I prevent my code from yielding every frame?

How can I get last time this method was called in seconds?

How can I access a parent method from child component in Vue.js?

How can I call method in the component from view? (vue.js 2)

Hi , how can i add a keyframe every time a score is being updated from a sports API so the score blinks for a couple of seconds if it changes?

In Pytest, how can I check if a method was called from another method?

How can I pass data from a component to another component on vue?

How can I stop pytorch model from downloading vgg .pth pretrained file every time I do inference?

How can I prevent React from unmounting/remounting a component?

How can I prevent a component from rendering before data is loaded?

How can I prevent Dreamweaver from running local code?

How can i prevent a jquery function from running?

How can I prevent an onclick JavaScript from running on page load?