我正在使用Vue.js加载HTML datalist。每当我输入连接到我的datalist的输入框时,我的页面就会冻结(使用Chrome)。我正在使用jQuery进行AJAX调用,最初在页面加载时获取所有用户,然后使用JavaScript过滤器函数创建一个新的数组,其中包含indexOf
输入框中输入的内容,然后放入新过滤的对象数组到datalist元素中。
这是我的HTML:
<div id="my-app">
<input list="user-search" type="text" id="find-user" name="find-user" v-model="findUser">
<datalist id="user-search">
<option v-for="user in findUserList">{{ user.vendorName }}</option>
</datalist>
</div>
这是我的Vue JavaScript:
var myApp = new Vue({
el: '#my-app',
data: {
users: [],
findUser: '',
findUserList: '',
},
watch: {
findUser: function(val) {
this.findUserResults();
}
},
methods: {
findUserResults: function() {
var lookFor = this.findUser.toLowerCase();
this.findUserList = this.users.filter(function(user) {
return (user.vendorName.toLowerCase().indexOf(myApp.findUser.toLowerCase()) > -1 || user.email.toLowerCase().indexOf(myApp.findUser.toLowerCase()) > -1);
});
},
loadUsers: function() {
$.ajax({
method: 'GET',
url: '/users',
success: function(data) {
myApp.users = JSON.parse(data);
},
error: function() {
console.log('error...');
}
});
}
},
mounted: function() {
this.loadUsers();
}
})
页面加载时用户加载正常。没有问题。我甚至评论了v-for
和console.log
'过滤器的结果也没有问题。当我在<option>
中动态添加<datalist>
值时,会出现此问题。我已尝试将选项包装在vue <template>
标记中,并将v-for
移到那里但没有成功。
我在其他页面上工作正常,但我填写的表格包含<tr>
和<td>
,而不是<datalist>
和<option>
。
可能导致我的网页崩溃的原因是什么? <datalist>
不足以处理所有这些问题吗?也许我错过了第二组眼睛可以帮助解决的问题。
修改
正在填充到users
的数据看起来像这样(它是一个对象数组):
[{id:1, vendorName:'john'}, {id:2, vendorName:'Rachel', {id:3, vendorName:'Steve'}]
ANSWER
这实际上只是某人过度思考(我)的一个例子。 B.Fleming关于这个递归的答案让我想到了为什么我的上述方法不正确。每次用户输入时都无需继续重新加载datalist选项。这正是与<datalist>
关联的<input>
所做的事情;不需要JavaScript。我需要(ed)做的就是在页面加载时将所有~3,000个用户加载到<datalist>
标记为<option>
(或者每当我想要显示输入和数据列表时),并让其余的是datalist和输入处理。我没有在上面的示例中使用应用程序对此进行测试,因为我不在那台计算机附近,但作为一个概念证明,数据列表可以处理数千个选项元素,我写了这个并在本地运行它没有问题(不知道为什么代码段控制台一直说它有效时会出错:
window.onload = function() {
var datalistElement = document.getElementById('datalist-test');
var datalistString = '';
for (var i = 0; i < 3000; i++) {
datalistString += '<option>' + Math.random().toString(36).substring(7); + '</option>';
}
datalistElement.innerHTML = datalistString;
}
<!DOCTYPE html>
<html>
<head>
<title>Datalist Test</title>
</head>
<body>
<input list="datalist-test" type="text">
<datalist id="datalist-test">
</datalist>
</body>
</html>
3,000个datalist选项元素,没关系。
答案 0 :(得分:1)
你有无限递归的电话。您在输入/删除搜索文本时调用myApp.findUser()
,调用myApp.findUserResults()
,调用myApp.findUser()
等。您需要解决此问题。
要解决此问题,您所要做的就是将所有用户加载到datalist选项中一次。然后,让输入框和datalist处理剩下的事情。每次用户输入时都无需继续重新加载datalist选项。
答案 1 :(得分:1)
通常情况下,您会使用computed property。我还做了一些其他的改变。首先,从内部引用Vue本身是一种不好的做法;只需使用this
。此外,datalist选项还具有您需要指定的value属性。
console.clear()
const users = [
{vendorName: "Vendor One", email: "bob@example.com"},
{vendorName: "Vendor Two", email: "mary@example.com"},
{vendorName: "Vendor Three", email: "jim@example.com"},
{vendorName: "Vendor Four", email: "joe@vendor.com"},
{vendorName: "Vendor Five", email: "sara@vendor.com"},
]
var myApp = new Vue({
el: '#my-app',
data: {
users: [],
findUser: '',
},
computed:{
vendors(){
return this.users.filter(u => {
return u.vendorName.toLowerCase().indexOf(this.findUser) > -1 ||
u.email.toLowerCase().indexOf(this.findUser) > -1
})
}
},
methods: {
loadUsers: function() {
// obviously, this is different for example purposes
this.users = users
}
},
mounted: function() {
this.loadUsers();
}
})
&#13;
<script src="https://unpkg.com/vue@2.4.2"></script>
<div id="my-app">
<h3>Type "V"</h3>
<input list="user-search" name="find-user" v-model="findUser">
<datalist id="user-search">
<option v-for="user in vendors" :value="user.vendorName">
</datalist>
</div>
&#13;