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 ajax abort()的使用方法
Oct 28 Javascript
js禁止小键盘输入数字功能代码
Aug 01 Javascript
JavaScript+html5 canvas绘制渐变区域完整实例
Jan 26 Javascript
BootStrap的Datepicker控件使用心得分享
May 25 Javascript
利用imgareaselect辅助后台实现图片上传裁剪
Mar 02 Javascript
vue-axios使用详解
May 10 Javascript
用Vue.extend构建消息提示组件的方法实例
Aug 08 Javascript
ES6中Array.find()和findIndex()函数的用法详解
Sep 16 Javascript
微信小程序实现列表下拉刷新上拉加载
Jul 29 Javascript
详解vue 自定义marquee无缝滚动组件
Apr 09 Javascript
JS查找孩子节点简单示例
Jul 25 Javascript
Vue使用mixin分发组件的可复用功能
Sep 01 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获取网站域名和地址的代码
2008/08/17 PHP
php FLEA中二叉树数组的遍历输出
2012/09/26 PHP
php文字水印和php图片水印实现代码(二种加水印方法)
2013/12/25 PHP
PHP合并静态文件详解
2014/11/14 PHP
Zend Framework实现多文件上传功能实例
2016/03/21 PHP
php图像验证码生成代码
2017/06/08 PHP
使Ext的Template可以解析二层的json数据的方法
2007/12/22 Javascript
DLL+ ActiveX控件+WEB页面调用例子
2010/08/07 Javascript
博客侧边栏模块跟随滚动条滑动固定效果的实现方法(js+jquery等)
2013/03/24 Javascript
jqGrid日期格式的判断示例代码(开始日期与结束日期)
2013/11/08 Javascript
基于jQuery的判断iPad、iPhone、Android是横屏还是竖屏的代码
2014/05/11 Javascript
jQuery+PHP星级评分实现方法
2015/10/02 Javascript
js验证真实姓名与身份证号是否匹配
2015/10/13 Javascript
Bootstrap布局组件应用实例讲解
2016/02/17 Javascript
JS实现Ajax的方法分析
2016/12/20 Javascript
js数组与字符串常用方法总结
2017/01/13 Javascript
Vue-router 类似Vuex实现组件化开发的示例
2017/09/15 Javascript
three.js实现3D视野缩放效果
2017/11/16 Javascript
值得收藏的vuejs安装教程
2017/11/21 Javascript
jQuery实现鼠标移入移出事件切换功能示例
2018/09/06 jQuery
详解ESLint在Vue中的使用小结
2018/10/15 Javascript
javascript使用链接跨域下载图片
2019/11/01 Javascript
JQuery通过键盘控制键盘按下与松开触发事件
2020/08/07 jQuery
Selenium的使用详解
2018/10/19 Python
python实现两个dict合并与计算操作示例
2019/07/01 Python
python中append实例用法总结
2019/07/30 Python
洛杉矶时尚女装系列:J.ING US
2019/03/17 全球购物
工程总经理工作职责
2013/12/09 职场文书
优秀演讲稿范文
2013/12/29 职场文书
开会迟到检讨书
2014/01/08 职场文书
党员干部公开承诺书范文
2015/04/27 职场文书
2015初中教导处工作总结
2015/07/21 职场文书
心得体会格式及范文
2016/01/25 职场文书
js Proxy的原理详解
2021/05/25 Javascript
javascript条件式访问属性和箭头函数介绍
2021/11/17 Javascript
什么是css原子化,有什么用?
2022/04/24 HTML / CSS