我正在Firebase支持的Vue.js中构建一个自动完成菜单(使用vue-fire)。目的是开始键入用户的显示名称,并在下面的div列表中显示匹配记录。
模板如下所示:
<b-form-input id="toUser"
type="text"
v-model="selectedTo"
@change="searcher">
</b-form-input>
<div v-on:click="selectToUser(user)" class="userSearchDropDownResult" v-for="user in searchResult" v-if="showSearcherDropdown">{{ user.name }}</div>
点击潜在匹配后,目的是设置字段的值并清除匹配列表。
以下是组件的代码部分:
computed: {
/* method borrowed from Reddit user imGnarly: https://www.reddit.com/r/vuejs/comments/63w65c/client_side_autocomplete_search_with_vuejs/ */
searcher() {
let self = this;
let holder = [];
let rx = new RegExp(this.selectedTo, 'i');
this.users.forEach(function (val, key) {
if (rx.test(val.name) || rx.test(val.email)) {
let obj = {}
obj = val;
holder.push(obj);
} else {
self.searchResult = 'No matches found';
}
})
this.searchResult = holder;
return this.selectedTo;
},
showSearcherDropdown() {
if(this.searchResult == null) return false;
if(this.selectedTo === '') return false;
return true;
}
},
methods: {
selectToUser: function( user ) {
this.newMessage.to = user['.key'];
this.selectedTo = user.name;
this.searchResult = null;
}
}
Typeahead运行良好,每次更改输入字段时,都会调用searcher()函数并使用正确的值填充searchResult。显示了v-for作品和div列表。
点击div后,我调用selectToUser(用户)。这会正确地将用户对象的详细信息报告给控制台。
然而,在第一次点击时我在控制台中得到一个异常并且div没有清除(我希望它们消失,因为我将searchResults设置为null)。
[Vue warn]: Error in event handler for "change": "TypeError: fns.apply is not a function"
found in
---> <BFormInput>
<BFormGroup>
<BTab>
TypeError: fns.apply is not a function
at VueComponent.invoker (vue.esm.js?efeb:2004)
at VueComponent.Vue.$emit (vue.esm.js?efeb:2515)
at VueComponent.onChange (form-input.js?1465:138)
at boundFn (vue.esm.js?efeb:190)
at invoker (vue.esm.js?efeb:2004)
at HTMLInputElement.fn._withTask.fn._withTask (vue.esm.js?efeb:1802)
如果我单击div 第二时间,则没有错误,输入值已设置且div消失。
所以我怀疑为this.selectedTo写了一个值(这也是元素的v模型对象触发了@change事件。在第二次点击时,值实际上没有改变,因为它已经设置了,所以没有调用searcher()而且没有错误。
我注意到如果元素失去焦点也会发生这种情况。
问题:如何在通过方法更改v-model值时阻止@change事件?
(其他信息:根据package.json我的vue 2.5.2)
答案 0 :(得分:0)
@acdcjunior,谢谢你的回答。
当然,删除对searcher()
的引用只意味着不会对字段值更改采取任何操作,因此该字段根本不起作用。
将searcher()
函数移动到methods: {}
而不是computed: {}
意味着它将在输入事件上调用而不是更改甚至(另一个神秘但今天不是一个)。一个微妙的差异,消除了我瞄准的先行功能。
然而,它确实让我记住computed: {}
函数的结果被缓存,并在任何参数更改时重新计算。在这种情况下,我意识到searcher()
函数依赖于this.selectedTo
变量。因此,当selectToUser()
函数设置this.selectedTo
时,它会触发对searcher()
的另一次调用。
现在修复。如果将来有人遇到类似的问题,我通过添加另一个变量转向老式信号量来解决这个问题。
var userMadeSelection: false
现在,搜索者()首先检查这种情况:
computed: {
searcher() {
if(this.userMadeSelection) {
this.userMadeSelection = false;
return this.selectedTo;
}
…
然后在selectToUser()中:
this.userMadeSelection = true;