
本文将指导你如何使用JavaScript实现一个具有智能搜索提示和数据验证功能的Autocomplete组件。该组件能够在用户输入时提供匹配的选项,支持在字符串的任意位置进行匹配,并且可以限制用户输入,只允许选择预定义的选项。
1. HTML结构
首先,我们需要一个HTML结构来容纳输入框和Autocomplete列表。
2. JavaScript实现Autocomplete功能
接下来,我们将使用JavaScript来实现Autocomplete的核心功能。
2.1 显示所有选项
要实现当光标位于空字段时显示所有选项,我们需要修改input事件监听器。当输入框为空时,显示整个列表。
inp.addEventListener("input", function(e) {
var a, b, i, val = this.value;
closeAllLists();
if (!val) {
// 显示所有选项
a = document.createElement("DIV");
a.setAttribute("id", this.id + "autocomplete-list");
a.setAttribute("class", "autocomplete-items");
this.parentNode.appendChild(a);
for (i = 0; i < arr.length; i++) {
b = document.createElement("DIV");
b.innerHTML = arr[i];
b.innerHTML += "";
b.addEventListener("click", function(e) {
inp.value = this.getElementsByTagName("input")[0].value;
closeAllLists();
});
a.appendChild(b);
}
return false;
}
currentFocus = -1;
a = document.createElement("DIV");
a.setAttribute("id", this.id + "autocomplete-list");
a.setAttribute("class", "autocomplete-items");
this.parentNode.appendChild(a);
for (i = 0; i < arr.length; i++) {
// 匹配任意位置的字符串
if (arr[i].toUpperCase().indexOf(val.toUpperCase()) > -1) {
b = document.createElement("DIV");
b.innerHTML = arr[i].replace(new RegExp(val, 'gi'), "$&");
b.innerHTML += "";
b.addEventListener("click", function(e) {
inp.value = this.getElementsByTagName("input")[0].value;
closeAllLists();
});
a.appendChild(b);
}
}
});2.2 匹配任意位置的字符串
要实现匹配字符串中任意位置的功能,我们需要修改匹配逻辑。不再使用substr(),而是使用indexOf()来检查匹配项。
if (arr[i].toUpperCase().indexOf(val.toUpperCase()) > -1) {
/*create a DIV element for each matching element:*/
b = document.createElement("DIV");
/*make the matching letters bold:*/
// 使用正则表达式高亮匹配的字符串
b.innerHTML = arr[i].replace(new RegExp(val, 'gi'), "$&");
b.innerHTML += "";
/*execute a function when someone clicks on the item value (DIV element):*/
b.addEventListener("click", function(e) {
/*insert the value for the autocomplete text field:*/
inp.value = this.getElementsByTagName("input")[0].value;
/*close the list of autocompleted values,
(or any other open lists of autocompleted values:*/
closeAllLists();
});
a.appendChild(b);
}2.3 限制输入并验证
为了限制用户只能输入Autocomplete列表中的值,我们需要在表单提交前进行验证,或者在每次输入后进行验证。这里提供一个简单的输入验证方法。
inp.addEventListener("blur", function() {
let currentValue = this.value;
let isValid = false;
for (let i = 0; i < arr.length; i++) {
if (arr[i] === currentValue) {
isValid = true;
break;
}
}
if (!isValid) {
this.value = ""; // 清空输入框
alert("请输入有效的水果名称"); // 提示用户
}
});这段代码在输入框失去焦点时(blur事件)触发,检查输入的值是否在fruitlist数组中。如果不在,则清空输入框并提示用户。
2.4 完整的JavaScript代码
function autocomplete(inp, arr) {
var currentFocus;
inp.addEventListener("input", function(e) {
var a, b, i, val = this.value;
closeAllLists();
if (!val) {
// 显示所有选项
a = document.createElement("DIV");
a.setAttribute("id", this.id + "autocomplete-list");
a.setAttribute("class", "autocomplete-items");
this.parentNode.appendChild(a);
for (i = 0; i < arr.length; i++) {
b = document.createElement("DIV");
b.innerHTML = arr[i];
b.innerHTML += "";
b.addEventListener("click", function(e) {
inp.value = this.getElementsByTagName("input")[0].value;
closeAllLists();
});
a.appendChild(b);
}
return false;
}
currentFocus = -1;
a = document.createElement("DIV");
a.setAttribute("id", this.id + "autocomplete-list");
a.setAttribute("class", "autocomplete-items");
this.parentNode.appendChild(a);
for (i = 0; i < arr.length; i++) {
if (arr[i].toUpperCase().indexOf(val.toUpperCase()) > -1) {
b = document.createElement("DIV");
b.innerHTML = arr[i].replace(new RegExp(val, 'gi'), "$&");
b.innerHTML += "";
b.addEventListener("click", function(e) {
inp.value = this.getElementsByTagName("input")[0].value;
closeAllLists();
});
a.appendChild(b);
}
}
});
inp.addEventListener("keydown", function(e) {
var x = document.getElementById(this.id + "autocomplete-list");
if (x) x = x.getElementsByTagName("div");
if (e.keyCode == 40) {
currentFocus++;
addActive(x);
} else if (e.keyCode == 38) {
currentFocus--;
addActive(x);
} else if (e.keyCode == 13) {
e.preventDefault();
if (currentFocus > -1) {
if (x) x[currentFocus].click();
}
}
});
function addActive(x) {
if (!x) return false;
removeActive(x);
if (currentFocus >= x.length) currentFocus = 0;
if (currentFocus < 0) currentFocus = (x.length - 1);
x[currentFocus].classList.add("autocomplete-active");
}
function removeActive(x) {
for (var i = 0; i < x.length; i++) {
x[i].classList.remove("autocomplete-active");
}
}
function closeAllLists(elmnt) {
var x = document.getElementsByClassName("autocomplete-items");
for (var i = 0; i < x.length; i++) {
if (elmnt != x[i] && elmnt != inp) {
x[i].parentNode.removeChild(x[i]);
}
}
}
document.addEventListener("click", function(e) {
closeAllLists(e.target);
});
inp.addEventListener("blur", function() {
let currentValue = this.value;
let isValid = false;
for (let i = 0; i < arr.length; i++) {
if (arr[i] === currentValue) {
isValid = true;
break;
}
}
if (!isValid) {
this.value = "";
alert("请输入有效的水果名称");
}
});
}
var fruitlist = [
"Apple",
"Mango",
"Pear",
"Banana",
"Berry"
];
autocomplete(document.getElementById("myFruitList"), fruitlist);3. CSS样式
为了使Autocomplete列表看起来更美观,我们可以添加一些CSS样式。
.autocomplete {
position: relative;
display: inline-block;
}
.autocomplete-items {
position: absolute;
border: 1px solid #d4d4d4;
border-bottom: none;
border-top: none;
z-index: 99;
top: 100%;
left: 0;
right: 0;
}
.autocomplete-items div {
padding: 10px;
cursor: pointer;
background-color: #fff;
border-bottom: 1px solid #d4d4d4;
}
.autocomplete-items div:hover {
background-color: #e9e9e9;
}
.autocomplete-active {
background-color: DodgerBlue !important;
color: #fff;
}4. 总结
通过以上步骤,我们实现了一个具有智能搜索提示和数据验证功能的Autocomplete组件。这个组件可以在用户输入时提供匹配的选项,支持在字符串的任意位置进行匹配,并且可以限制用户输入,只允许选择预定义的选项。你可以根据自己的需求,进一步扩展和优化这个组件。
注意事项
- 在实际应用中,可以考虑使用节流或防抖技术来优化输入事件的处理,减少不必要的计算。
- 可以从服务器端获取Autocomplete列表,以支持更大的数据集。
- 可以添加更多的验证规则,例如检查输入是否为空,或者是否符合特定的格式。
- 为了更好的用户体验,可以添加键盘导航功能,允许用户使用键盘上下键选择Autocomplete列表中的选项。










