搜索框Demo
记录一个搜索框的demo,搜索图标在阿里矢量图标库下载
效果图展示
-
常态图如下:
-
获得焦点的输入框
-
有内容输入时,展示关联的列表,可以点击列表项;也可以按上下箭头选择,然后按回车键选择列表项
代码
html部分如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<input type="text">
<div class="list"></div>
<script src="index.js"></script>
</body>
</html>
js部分如下:
const input = document.querySelector('input');
const listDiv = document.querySelector('.list');
// 模拟数据
let infos = [
{ id: 1, name: '《JavaScript高级程序设计》' },
{ id: 2, name: '《JavaScript高级程序设计》' },
{ id: 3, name: '《JavaScript高级程序设计》' },
{ id: 4, name: '《JavaScript高级程序设计》' },
{ id: 5, name: '《JavaScript高级程序设计》' },
{ id: 6, name: '《JavaScript高级程序设计》' },
{ id: 7, name: '《JavaScript高级程序设计》' },
{ id: 8, name: '《JavaScript高级程序设计》' },
{ id: 9, name: '《JavaScript高级程序设计》' },
{ id: 10, name: '《JavaScript高级程序设计》' },
{ id: 11, name: '《JavaScript高级程序设计》' },
{ id: 12, name: '《JavaScript高级程序设计》' },
{ id: 13, name: '《JavaScript高级程序设计》' },
{ id: 14, name: '《JavaScript高级程序设计》' },
{ id: 15, name: '《JavaScript高级程序设计》' },
]
// input联想列表选中项的索引
let index = 0;
// input的旧值
let oldValue = "";
// input联想列表的长度
let tmpListLenth = 10;
input.addEventListener('keyup', (e) => {
keyUpEvent(e);
})
input.addEventListener('blur', () => {
listDiv.classList.remove('listActive');
input.value = "";
})
listDiv.addEventListener('mousedown', (e) => {
mouseDownEvent(e, e.target.getAttribute('key'));
})
function filterList(inputValue, allList) {
inputValue = inputValue.length > 10 ? inputValue.slice(0, 10) : inputValue;
let tmpList = allList.slice(0, 11 - inputValue.length);
return tmpList;
}
function keyUpEvent(e) {
let tmpValue = input.value.trim();
// 四种情况,一种render,两种innerHtml = "",一种不处理
if (tmpValue) {
if (oldValue !== tmpValue) {
listDiv.classList.add('listActive');
let tmpList = filterList(tmpValue, infos);
renderList(tmpList);
tmpListLenth = tmpList.length;
}
} else {
listDiv.innerHTML = "";
}
oldValue = tmpValue;
// keyCode:40
if (e.key === "ArrowDown") {
index = index !== tmpListLenth - 1 ? index + 1 : 0;
arrowEvent();
}
// keyCode:38
if (e.key === "ArrowUp") {
index = index !== 0 ? index - 1 : tmpListLenth - 1;
arrowEvent();
}
// keyCode:13
if (e.key === "Enter") {
let selectedBook = document.querySelector('.bookActive');
mouseDownEvent(e, selectedBook.getAttribute('key'));
}
}
// enter或者mousedown,要根据选中的元素做点事情
function mouseDownEvent(e, id) {
e.preventDefault();
input.value = '';
input.blur();
}
// 按上下箭头,修改列表样式
function arrowEvent() {
const bookList = document.querySelectorAll('.bookItem');
// 空数组不会执行回调函数
bookList.forEach(function (item) {
item.classList.remove('bookActive');
if (item.getAttribute('key') == index) {
item.classList.add('bookActive');
}
})
}
// input框中的值变化且不为空,先清空,再重新渲染列表
function renderList(tmpList) {
listDiv.innerHTML = "";
console.log('render');
// 实际情况,直接根据传入的tmpList渲染
var bookTemplate = tmpList.map((item, index) => {
return `<div class="bookItem" key=${index}>${item.id}. ${item.name}</div>`
}).join('');
listDiv.innerHTML = bookTemplate;
index = 0;
arrowEvent();
}
css部分如下:
input {
background: url("./search.svg") no-repeat;
background-position: 10px;
background-size: 25px 25px;
position: absolute;
top: 30%;
left: 50%;
transform: translateX(-50%);
height: 50px;
width: 400px;
border: 1px solid rgb(191,191,191);
border-radius: 25px;
box-shadow: 2px 2px 2px #eee;
padding-left: 40px;
font-size: 16px;
}
/* input边框的颜色,默认是outline控制的,不是border */
/* jQuery设置的border会生效(未尝试) */
input:focus {
background-image: url("./search-active.svg");
border-color: #66afe9;
outline: none;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
}
.list {
visibility: hidden;
width: 410px;
/* height: 300px; */
box-shadow: 2px 2px 5px rgb(191,191,191);
position: absolute;
left: 50%;
top: calc(30% + 55px);
transform: translateX(-50%);
}
.listActive {
visibility: visible;
}
.bookItem {
height: 30px;
border-bottom: 1px solid rgb(236,236,236);
line-height: 30px;
}
.bookItem:hover {
background-color: rgb(236,236,236);
}
.bookActive {
background-color: rgb(236,236,236);
}