JS实现百度搜索框


Posted in Javascript onFebruary 25, 2021

本文实例为大家分享了JS实现百度搜索框的具体代码,供大家参考,具体内容如下

实现原理

向输入框动态输入时关键词,将当前关键词作为问号参数后面的值,因为要跨域使用百度的接口,所以通过 JSONP 跨域创建 Ajax 请求。回调函数处理返回值。

尝试研究了一下百度的接口,发现原生的 XHR 接口参数有点复杂(百度应该是考虑了很多情况)。

找了一个 2345 导航,在输入框随便输入一个字母 s,打开 Network,发现它也是向百度的一个地址发送了请求,其中问号后面的‘&wd=s'发送的就是此关键词,'&cb='应该就是回调处理函数,并且它的 Type 也是 script,2345 导航应该也是通过 JSONP 向百度获取数据的。

JS实现百度搜索框

var script = document.createElement("script");
script.src =
 "https://www.baidu.com/su?&wd=" +
 encodeURI(this.value.trim()) +
 "&p=3&cb=handleSuggestion";
document.body.appendChild(script);

点开那条请求,果然在里面看到了返回的数据。返回的结果是以一个对象的形式返回的。q 对应着检索关键词,s 对应着返回的结果(数组形式)

JS实现百度搜索框

后续只需要动态创建 li 标签,设置里面的内容,以及注意其他细节问题。

1.使用 flex 布局实现搜索框的水平垂直居中。

坑 设置完 flex 属性之后发现并没有水平垂直居中,当时设置了父盒子 height:100%,发现如果将 height 设置成具体值就可以实现居中。怀疑是设置了%高度无效,查了一下,高度百分比是相对于父盒子的,也就是 body。默认 html 和 body 是没有设置 height 的。另外,在布局中对于没有设置宽高的块状盒子,宽度默认是 100%的,高度是由里面的内容自然撑开的。

2.先获取常用的 DOM 节点,避免后续频繁查询操作 DOM。

3.为了避免在输入过程中频繁发送请求(如果打字速度快),对请求函数做了函数节流,调了一下间隔 130ms 差不多正好,时间再长就会有卡顿的感觉。使用了 ES6 中的箭头函数避免了 setTimeout 中 this 指向的问题。

4.在回调函数中:

  • 每一次执行时首先要清除建议框里的内容,不然上一次的结果还会存在建议框里!截取了结果中的前五个(如果把所有结果都展示出来感觉有点丑…百度官方是展示前四个搜索建议)
  • 结果处理完毕后,执行自执行匿名函数,删除创建的 script 标签;

5.由于 li 是动态创建的,点击 li 标签或者点击"搜索一下"跳转百度进行搜索时,利用事件冒泡原理,进行事件委托。这里没有考虑兼容性问题:

e = e || window.event;
target = e.target || e.srcElement;

6.除了点击事件,键盘事件?回车键以及上下键都是进行事件委托进行注册的。

最终能够实现键盘上下键鼠标选择,点击“搜索一下”或回车键实现跳转搜索。

代码:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <!-- 兼容性视图 -->
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <meta content="更方便快捷搜索,从而达到事半功倍的效果" name="description">
 <title>search you want</title>
 <style>
 html {
 height: 100%;
 }

 body {
 background: #f0f3ef;
 height: 100%;
 }

 .container {
 height: 100%;
 display: flex;
 justify-content: center;
 align-items: center;
 flex-direction: column;
 }

 .bgDiv {
 box-sizing: border-box;
 width: 595px;
 height: 55px;
 position: relative;
 /* position: absolute;
 left: 50%;
 top: 50%;
 transform: translate(-50%, -50%); */
 }

 .search-input-text {
 border: 1px solid #b6b6b6;
 width: 495px;
 background: #fff;
 height: 33px;
 line-height: 33px;
 font-size: 18px;
 padding: 3px 0 0 7px;
 }

 .search-input-button {
 width: 90px;
 height: 38px;
 color: #fff;
 font-size: 16px;
 letter-spacing: 3px;
 background: #3385ff;
 border: .5px solid #2d78f4;
 margin-left: -5px;
 vertical-align: top;
 opacity: .9;
 }

 .search-input-button:hover {
 opacity: 1;
 box-shadow: 0 1px 1px #333;
 cursor: pointer;
 }

 .suggest {
 width: 502px;
 position: absolute;
 top: 38px;
 border: 1px solid #999;
 background: #fff;
 display: none;
 }

 .suggest ul {
 list-style: none;
 margin: 0;
 padding: 0;
 }

 .suggest ul li {
 padding: 3px;
 font-size: 17px;
 line-height: 25px;
 cursor: pointer;
 }

 .suggest ul li:hover {
 background-color: #e5e5e5
 }
 </style>
</head>

<body>
 <div class="container">
 <div class="bgDiv">
 <input type="text" class="search-input-text" value="" autofocus placeholder="关键词">
 <input type="button" value="搜索一下" class="search-input-button" id="btn">
 <div class="suggest">
 <ul id="search-result">
 </ul>
 </div>
 </div>
 </div>

 <script>
 var suggestContainer = document.getElementsByClassName("suggest")[0];
 var searchInput = document.getElementsByClassName("search-input-text")[0];
 var bgDiv = document.getElementsByClassName("bgDiv")[0];
 var searchResult = document.getElementById("search-result");

 // 清除建议框内容
 function clearContent() {
 var size = searchResult.childNodes.length;
 for (var i = size - 1; i >= 0; i--) {
 searchResult.removeChild(searchResult.childNodes[i]);
 }
 };

 var timer = null;
 // 注册输入框键盘抬起事件
 searchInput.onkeyup = function (e) {
 suggestContainer.style.display = "block";
 // 如果输入框内容为空 清除内容且无需跨域请求
 if (this.value.length === 0) {
 clearContent();
 return;
 }
 if (this.timer) {
 clearTimeout(this.timer);
 }
 if (e.keyCode !== 40 && e.keyCode !== 38) {
 // 函数节流优化
 this.timer = setTimeout(() => {
 // 创建script标签JSONP跨域
 var script = document.createElement("script");
 script.src = "https://www.baidu.com/su?&wd=" + encodeURI(this.value.trim()) +
 "&p=3&cb=handleSuggestion";
 document.body.appendChild(script);
 }, 130)
 }

 };

 // 回调函数处理返回值
 function handleSuggestion(res) {
 // 清空之前的数据!!
 clearContent();
 var result = res.s;
 // 截取前五个搜索建议项
 if (result.length > 4) {
 result = result.slice(0, 5)
 }
 for (let i = 0; i < result.length; i++) {
 // 动态创建li标签
 var liObj = document.createElement("li");
 liObj.innerHTML = result[i];
 searchResult.appendChild(liObj);
 }
 // 自执行匿名函数--删除用于跨域的script标签
 (function () {
 var s = document.querySelectorAll('script');
 for (var i = 1, len = s.length; i < len; i++) {
 document.body.removeChild(s[i]);
 }
 })()
 }


 function jumpPage() {
 window.open(`https://www.baidu.com/s?word=${encodeURI(searchInput.value)}`);
 }

 // 事件委托 点击li标签或者点击搜索按钮跳转到百度搜索页面
 bgDiv.addEventListener("click", function (e) {
 if (e.target.nodeName.toLowerCase() === 'li') {
 var keywords = e.target.innerText;
 searchInput.value = keywords;
 jumpPage();
 } else if (e.target.id === 'btn') {
 jumpPage();
 }
 }, false);

 var i = 0;
 var flag = 1;

 // 事件委托 监听键盘事件
 bgDiv.addEventListener("keydown", function (e) {
 var size = searchResult.childNodes.length;
 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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery 1.0.4 - New Wave Javascript(js源文件)
Jan 15 Javascript
Prototype Selector对象学习
Jul 23 Javascript
老鱼 浅谈javascript面向对象编程
Mar 04 Javascript
动态加载script文件的两种方法
Aug 15 Javascript
JavaScript中的公有、私有、特权和静态成员用法分析
Nov 20 Javascript
使用ionic切换页面卡顿的解决方法
Dec 16 Javascript
使用ionic在首页新闻中应用到的跑马灯效果的实现方法
Feb 13 Javascript
Bootstrap布局之栅格系统学习笔记
May 04 Javascript
jQuery实现frame之间互通的方法
Jun 26 jQuery
使用vue如何构建一个自动建站项目
Feb 05 Javascript
layui 富文本编辑器和textarea值的相互传递方法
Sep 18 Javascript
解决vscode进行vue格式化,会自动补分号和双引号的问题
Oct 26 Javascript
基于JavaScript实现随机点名器
Feb 25 #Javascript
JavaScript仿京东轮播图效果
Feb 25 #Javascript
Vue基本指令实例图文讲解
Feb 25 #Vue.js
使用webpack和rollup打包组件库的方法
Feb 25 #Javascript
vue常用高阶函数及综合实例
Feb 25 #Vue.js
原生JS实现音乐播放器的示例代码
Feb 25 #Javascript
详解vite2.0配置学习(typescript版本)
Feb 25 #Javascript
You might like
PHP使用DOMDocument类生成HTML实例(包含常见标签元素)
2014/06/25 PHP
php中substr()函数参数说明及用法实例
2014/11/15 PHP
QQ登录简单实现代码
2021/03/09 Javascript
JavaScript将数据转换成整数的方法
2014/01/04 Javascript
JQuery中使用on方法绑定hover事件实例
2014/12/09 Javascript
13 款最热门的 jQuery 图像 360 度旋转插件推荐
2014/12/09 Javascript
AngularJs  Creating Services详解及示例代码
2016/09/02 Javascript
第一次接触Bootstrap框架
2016/10/24 Javascript
select自定义小三角样式代码(实用总结)
2017/08/18 Javascript
纯js实现隔行变色效果
2017/11/29 Javascript
利用vue.js把静态json绑定bootstrap的table方法
2018/08/28 Javascript
一篇文章介绍redux、react-redux、redux-saga总结
2019/05/23 Javascript
JavaScript判断对象和数组的两种方法
2019/05/31 Javascript
微信小程序设置滚动条过程详解
2019/07/25 Javascript
基于vue.js仿淘宝收货地址并设置默认地址的案例分析
2020/08/20 Javascript
Python内置函数的用法实例教程
2014/09/08 Python
python通过文件头判断文件类型
2015/10/30 Python
Python面向对象之接口、抽象类与多态详解
2018/08/27 Python
tesserocr与pytesseract模块的使用方法解析
2019/08/30 Python
Python使用Opencv实现图像特征检测与匹配的方法
2019/10/30 Python
python读取图片的几种方式及图像宽和高的存储顺序
2020/02/11 Python
python pandas.DataFrame.loc函数使用详解
2020/03/26 Python
python中的错误如何查看
2020/07/08 Python
利用python如何实现猫捉老鼠小游戏
2020/12/04 Python
一文彻底解决HTML5页面中长按保存图片功能
2019/06/10 HTML / CSS
Champion澳大利亚官网:美国冠军运动服装
2018/05/07 全球购物
纽约州一群才华横溢的金匠制作而成:Hearth Jewelry
2019/03/22 全球购物
俄语翻译实习生的自我评价分享
2013/11/06 职场文书
公司董事长职责
2013/12/12 职场文书
重阳节活动总结
2014/08/27 职场文书
个人融资协议书范本两则
2014/10/15 职场文书
学校2014年度工作总结
2014/12/06 职场文书
会计稽核岗位职责
2015/04/13 职场文书
2019自荐信该如何写呢?
2019/07/05 职场文书
导游词之镇江焦山
2019/11/21 职场文书
MySQL 分页查询的优化技巧
2021/05/12 MySQL