实现一个搜索框并实时返回搜索建议项

参考:https://blog.csdn.net/rujin_shi/article/details/83657566

<!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>JS实现仿百度搜索框(实时返回搜索建议项)</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    html, body {
      height: 100%;
    }
    body {
      background-color: #f0f3ef;
    }
    div {
      box-sizing: border-box;
    }
    .container {
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      flex-direction: column;
    }
    .bgDiv {
      width: 595px;
      height: 55px;
      position: relative;
    }
    .input-wrapper {
      display: flex;
      justify-content: center;
      width: 100%;
      height: 33px;
    }
    .search-input-text {
      width: 560px;
      border: 1px solid #b6b6b6;
      background-color: #fff;
      font-size: 18px;
      padding: 3px 0 0 7px;
    }
    .search-input-button {
      flex: 1;
      color: #fff;
      font-size: 16px;
      letter-spacing: 3px;
      background-color: #3385ff;
      border: .5px solid #2d78f4;
      opacity: .9;
      margin-left: -5px;
    }
    .search-input-button:hover {
      opacity: 1;
      box-shadow: 0 1px 1px #333;
      cursor: pointer;
    }
    .suggest {
      width: 516px;
      position: absolute;
      top: 38px;
      border: 1px solid #999;
      background-color: #fff;
      display: none;
    }
    .suggest ul {
      list-style: none;
    }
    .suggest ul li {
      margin: 3px;
      font-size: 17px;
      line-height: 25px;
      cursor: pointer;
    }
    .suggest ul li:hover {
      background-color: #e5e5e5;
    }
  </style>
</head>
<!-- 向输入框动态输入关键词时,将当前关键词作为问号参数后面的值,
  因为要跨域使用百度的接口,所以通过JSONP跨域创建Ajax请求,回调函数处理返回值 -->
<body>
<!-- 默认html和body是没有设置height的,在布局中对于没有设置宽高的块状盒子,宽度
默认100%,高度是由里面的内容自然撑开的 -->
  <div class="container">
    <div class="bgDiv">
      <div class="input-wrapper">
        <input type="text" class="search-input-text" value="" autofocus placeholder="关键词">
        <input type="button" id="btn" class="search-input-button" value="搜索一下">
      </div>
      <div class="suggest">
        <ul id="search-result">
          <!-- 动态创建li,同时进行事件委托,键盘事件--回车键以及上下键都是进行事件委托注册的 -->
        </ul>
      </div>
    </div>
  </div>
  <script>
    let suggestContainer = document.getElementsByClassName('suggest')[0];
    let searchInput = document.getElementsByClassName('search-input-text')[0];
    let bgDiv = document.getElementsByClassName('bgDiv')[0];
    let searchResult = document.getElementById('search-result');
    //清除建议框内容
    let clearContent = function() {
      let size = searchResult.childNodes.length;
      for(let i = size - 1; i >= 0; i--) {
        searchResult.removeChild(searchResult.childNodes[i]);
      }
    }
    let timer = null;
    //注入输入框键盘抬起事件
    searchInput.onkeyup = function(e) {
      suggestContainer.style.display = 'block';
      //如果输入框内容为空,清除内容且无需跨域请求
      if(this.value.length === 0) {
        clearContent();
        return;
      }
      if(this.timer) {
        clearTimeout(this.timer);
      }
      //40为Dw arrow  38位Up Arrow
      if(e.keyCode !== 40 && e.keyCode !== 38) {
        //函数节流优化
        this.timer = setTimeout(() => {
          //创建script标签JSONP跨域
          let script = document.createElement("script");
          script.src = "http://www.baidu.com/su?&wd=" + encodeURI(this.value.trim()) + 
          "&p=3&cb=handleSuggestion";
          document.body.appendChild(script);
        }, 130);
      }
    }
    //回调函数处理返回值
    let handleSuggestion = function(res) {
      //清空之间的数据
      clearContent();
      let result = res.s;
      //截取前五个搜索建议项
      if(result.length > 4) {
        result = result.slice(0, 5);
      }
      //动态创建li标签,显示搜索建议项
      for(let i = 0; i < result.length; i++) {
        let liObj = document.createElement('li');
        liObj.innerHTML = result[i];
        searchResult.appendChild(liObj);
      }
      //自执行匿名函数--删除用于跨域的script标签
      (function() {
        let s = document.querySelectorAll("script");
        for(let i = 1, len = s.length; i < len; i++) {
          document.body.removeChild(s[i]);
        }
      })();
    }
    let jumpPage = function() {
      window.open(`https://www.baidu.com/s?word=${encodeURI(searchInput.value)}`);
    }
    //事件委托,点击li标签或者点击搜索按钮跳转到百度搜索页面
    bgDiv.addEventListener('click', function(e) {
      if(e.target.nodeName.toLowerCase() === 'li') {
        let keywords = e.target.innerText;
        searchInput.value = keywords;
        jumpPage();
      } else if(e.target.id === 'btn') {
        jumpPage();
      }
    }, false);
    let i = 0, flag = 1;//键盘向上和向下的区分标志
    //事件委托,监听键盘事件
    bgDiv.addEventListener('keydown', function(e) {
      let size = searchResult.childNodes.length;
      //13为enter
      if(e.keyCode === 13) {
        jumpPage();
      }
      //键盘向下事件
      if(e.keyCode === 40) {
        if(flag === 0) {
          i = i + 2;
        }
        flag = 1;
        e.preventDefault();
        if(i >= size) {
          i = 0;
        }
        if(i < size) {
          searchInput.value = searchResult.childNodes[i++].innerText;
        }
      }
      //键盘向上事件
      if(e.keyCode === 38) {
        if(flag === 1) {
          i = i - 2;
        }
        flag = 0;
        e.preventDefault();
        if(i < 0) {
          i = size - 1;
        }
        if(i > -1) {
          searchInput.value = searchResult.childNodes[i--].innerText;
        }
      }
    }, false);
    //点击页面上任何其它地方,搜索结果框消失
    document.onclick = () => clearContent();
  </script>
</body>
</html>
posted @ 2021-09-19 15:04  lihao_Q  阅读(270)  评论(0编辑  收藏  举报