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:
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>
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?
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.
Comments