我有一个Vue 2应用程序,它使用一组对象来支持vue-multiselect提供的搜索/多选小部件。
我看过Vue 1 - > 2 debouncing calls上的迁移指南,但它们提供的示例并没有将参数从DOM元素传播到业务逻辑。
现在,每次按键时,选择会触发更改事件,但是我想对此进行限制(EG使用lodash#throttle),这样我就不会在他们打字的时候每几毫秒点击一次我的API。 / p>
import {mapGetters} from 'vuex';
import { throttle } from 'lodash';
import Multiselect from 'vue-multiselect'
export default {
components: {
Multiselect
},
data() {
return {
selectedWork: {},
works: [],
isLoading: false
}
},
computed: {
...mapGetters(['worksList']),
},
methods: {
getWorksAsync: throttle((term) => {
// the plan is to replace this with an API call
this.works = this.worksList.filter(work => titleMatches(work, term));
}, 200)
}
}
问题:当用户在选择框中输入内容时,出现错误:
TypeError: Cannot read property 'filter' of undefined
正在发生这种情况,因为this.worksList
undefined
函数中throttle
为this.worksList
。
奇怪的是,当我使用开发工具调试器时,this
具有我需要取消引用的值,this
引用了Vue组件。
目前我没有从组件中调用API,但问题仍然存在:
this.works
上下文来更新我的function
列表?编辑:这在Vue Watch doesnt Get triggered when using axios Vue 2中的正确模式是什么?
答案 0 :(得分:0)
我无法在SO(或任何地方)找到答案,但我最终通过反复试验,以及此处和文档中的相关材料将它拼凑在一起。
有效的事情,我没有做,以及为什么
可以使用JavaScript DOM查询直接获取值,也可以深入了解多选组件的结构并获取值。第一种解决方案绕过框架,第二种解决方案取决于多选组件的未记录属性。我避免这两种解决方案都是非惯用和脆弱的。
我目前的解决方案
throttle
而不是箭头功能传递给this
,后者提供了正确的<template>
<div>
<label
class="typo__label"
for="ajax">Async select</label>
<multiselect
id="ajax"
v-model="selectedWork"
label="title"
track-by="id"
placeholder="Type to search"
:options="works"
:searchable="true"
:loading="isLoading"
:internal-search="false"
:multiple="false"
:clear-on-select="true"
:close-on-select="true"
:options-limit="300"
:limit="3"
:limit-text="limitText"
:max-height="600"
:show-no-results="false"
open-direction="bottom"
@select="redirect"
@search-change="updateSearchTerm">
<span slot="noResult">Oops! No elements found. Consider changing the search query.</span>
</multiselect>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import { throttle } from 'lodash';
import Multiselect from 'vue-multiselect'
export default {
components: {
Multiselect
},
data() {
return {
searchTerm: '',
selectedWork: {},
works: [],
isLoading: false
}
},
computed: {
...mapGetters(['worksList']),
},
methods: {
limitText(count) {
return `and ${count} other works`;
},
redirect(work) {
// redirect to selected page
},
updateSearchTerm(term){
this.searchTerm = term;
this.isLoading = true;
this.getWorksAsync();
},
getWorksAsync: throttle(function() {
const term = this.searchTerm.toLowerCase();
callMyAPI(term)
.then(results => {
this.works = results;
this.isLoading = false;
})
}, 200)
}
}
</script>
(Vue组件)。如果有人建议在Vue 2中采用更好的方式做到这一点,那么我全心全意。
这是我的解决方案最终的样子:
| id | name |
|-------|---------------------------------------------------------------------------------------|
| a1xy | [ { "event": "sports", "start": "100"}, { "event": "lunch", "start": "121" } ] |
| a7yz | [ { "event": "lunch", "start": "109"}, { "event": "movie", "start": "97" } ] |
| bx4y | [ { "event": "dinner", "start": "78"}, { "event": "sleep", "start": "25" } ] |
答案 1 :(得分:0)
使用lodash.debounce
时遇到了同样的问题。我是箭头语法的忠实粉丝,但我发现它导致_.throttle()
和_.debounce()
等失败。
显然我的代码与你的代码有所不同,但我做了以下工作并且有效:
export default {
...,
methods: {
onClick: _.debounce(function() {
this.$emit('activate', this.item)
}, 500)
}
}
即使我在这里没有使用箭头语法,this
仍引用去抖动函数内的组件。
在您的代码中,它看起来像这样:
export default {
...,
methods: {
getWorksAsync: throttle(function(term) {
// the plan is to replace this with an API call
this.works = this.worksList.filter(work => titleMatches(work, term));
}, 200)
}
}
希望有所帮助!