我所拥有的:
自动完成元素
<div v-for="(user, index) in users">
<input v-model="user.name"
:list="users-autocomplete" @input="autocompleteUser(user.name, index)"/>
<datalist :id="users-autocomplete">
<option v-for="user in usersAutocomplete" v-bind:value="user.name"
v-bind:label="user.name"></option>
</datalist>
</div>
数据
data() {
return {
users: [{
name: ''
}]
usersAutocomplete: []
}
},
方法
async autocompleteUser(value, index) {
let that = this
await axios.get(//fetching data)
.then(response => {
that.usersAutocomplete = response.data
})
}
问题与使用流程有关:
autocompleteUser()
将一些数据放入usersAutocomplete
,而不是<datalist>
。@input="autocompleteUser(user.name, index)"
又被解雇了!axios
再次获取数据,<datalist>
再次刷新。选择建议后,如何防止触发@input
?现在,我必须单击两次。
我试图将@click
绑定到<datalist>
或<option>
上,但是没有用。
答案 0 :(得分:1)
似乎,如果对event.data进行类型检查,如果输入事件由数据列表触发,则返回undefined。为什么会这样,我目前不知道。
因此解决此问题的一种简单但 hacky 方法可能是如果event.data未定义,则返回:
if(event.data === undefined) return;
我在发表评论后意识到您有很多用户。因此,除非您进行大量循环,否则观察者将无法正常工作。
请注意,我无法解释此解决方案,并且从未使用过dataLists,因此不能保证这是一个好的解决方案。
编辑:通过添加一些逻辑,您可以以编程方式模糊输入元素,这将导致删除该选项:
if(e.data === undefined) {
const allUserNames = this.usersAutocomplete.map(user => user.name)
if(allUserNames.includes(value))
this.$refs.myInput[0].blur();
return
}
new Vue({
el: '#vue',
data() {
return {
users: [{
name: ''
}],
usersAutocomplete: []
}
},
methods: {
autocompleteUser(e, value, index) {
if(e.data === undefined) {
const allUserNames = this.usersAutocomplete.map(user => user.name)
if(allUserNames.includes(value))
this.$refs.myInput[0].blur();
return
}
this.dummyAsync()
.then(response => {
console.log("autocompleteUser executed")
this.usersAutocomplete = response
})
},
dummyAsync() {
const data = [
{name: 'John Doe'},
{name: 'Jane Doe'},
{name: 'Bobby Doe'}
]
return new Promise(resolve => {
setTimeout(function() {
resolve(data);
}, 400); //Wannabe network delay
});
}
}
})
Vue.config.productionTip = Vue.config.devtools = false
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<main id="vue">
<div v-for="(user, index) in users">
<input v-model="user.name"
list="usersAutocomplete"
ref="myInput"
@input="autocompleteUser($event, user.name, index)"
/>
<datalist id="usersAutocomplete">
<option v-for="user in usersAutocomplete"
:value="user.name"
:label="user.name"
/>
</datalist>
</div>
</main>
答案 1 :(得分:1)
这现在对我有用。非常感谢Sølve Tornøe。
我开始调查InputEvent
。我发现一件事:在输入中键入内容时,会触发InputEvent
,inputType: insertText
对象中有一个InputEvent
。
通过单击<datalist>
选项更改输入值时,事件对象中不存在此类字段,并且事件实际上是Event
,而不是InputEvent
。
在模板中,我们必须添加事件参数以通过:@input="autocompleteUser($event, user.nickname, index)"
比相应的更改方法:
async autocompleteUser(e, value, index) {
if (e.inputType !== 'insertText') {
//input value is modified not by typing in the input
//so we can clear our data source, used for datalist
this.usersAutocomplete = []
return
}
let that = this
await axios.get(//fetching data)
.then(response => {
that.usersAutocomplete = response.data
})
}
UPD:由于以下原因在Firefox中不起作用
if (e.inputType !== 'insertText') {
this.usersAutocomplete = []
return
}
UPD2:修复
if (e.constructor.name !== 'InputEvent') {
this.usersAutocomplete = []
return
}