我正在 Vue.js 中构建一个由 Firebase 支持的自动完成菜单(使用 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>
Run Code Online (Sandbox Code Playgroud)
单击潜在匹配项后,目的是设置该字段的值并清除匹配项列表。
这是组件的代码部分:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
Typeahead 运行良好,每次更改输入字段时,都会调用 searcher() 函数并使用正确的值填充 searchResult。显示了 v-for 和 div 列表。
单击 div 后,我调用 selectToUser( user )。这可以正确地将用户对象的详细信息报告给控制台。
但是,在第一次单击时,我在控制台中遇到异常并且 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)
Run Code Online (Sandbox Code Playgroud)
如果我第二次单击 div则没有错误,输入值已设置并且 div 消失。
所以我怀疑向 this.selectedTo(这也是元素的 v-model 对象)写入一个值会触发 @change 事件。在第二次点击时,值实际上并没有改变,因为它已经设置了,所以没有调用到 searcher() 并且没有错误。
我注意到如果元素失去焦点也会发生这种情况。
问题:通过方法更改 v-model 值时如何防止 @change 事件?
(其他信息:根据 package.json 我在 vue 2.5.2)
@acdcjunior,感谢您的回答。
\n\n当然,仅删除对的引用searcher()意味着对字段值更改不采取任何操作,因此该字段根本无法工作。
将searcher()函数移入methods: {}而不是意味着computed: {}它将在输入事件上被调用,甚至不会发生变化(另一个谜团,但不是今天的谜团)。一个微妙的差异消除了 I\xe2\x80\x99m 所瞄准的预输入功能。
然而,它确实让我记住,函数的结果computed: {}是被缓存的,并且当任何参数发生变化时将重新计算。在这种情况下,我意识到该searcher()函数依赖于this.selectedTo变量。因此,当selectToUser()函数设置时this.selectedTo,它会触发另一个对searcher().
现在修好了。如果将来有人遇到类似的问题,我通过添加另一个变量转向老式信号量来解决这个问题。
\n\nvar userMadeSelection: false\nRun Code Online (Sandbox Code Playgroud)\n\n现在,searcher() 首先检查这种情况:
\n\n computed: {\n searcher() {\n if(this.userMadeSelection) {\n this.userMadeSelection = false;\n return this.selectedTo;\n }\n \xe2\x80\xa6\nRun Code Online (Sandbox Code Playgroud)\n\n然后在 selectToUser() 中:
\n\nthis.userMadeSelection = true;\nRun Code Online (Sandbox Code Playgroud)\n