本文实例为大家分享了JS实现百度搜索框的具体代码,供大家参考,具体内容如下
实现原理
向输入框动态输入时关键词,将当前关键词作为问号参数后面的值,因为要跨域使用百度的接口,所以通过 JSONP 跨域创建 Ajax 请求。回调函数处理返回值。
尝试研究了一下百度的接口,发现原生的 XHR 接口参数有点复杂(百度应该是考虑了很多情况)。
找了一个 2345 导航,在输入框随便输入一个字母 s,打开 Network,发现它也是向百度的一个地址发送了请求,其中问号后面的‘&wd=s'发送的就是此关键词,'&cb='应该就是回调处理函数,并且它的 Type 也是 script,2345 导航应该也是通过 JSONP 向百度获取数据的。
1
2
3
4
5
6
|
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 对应着返回的结果(数组形式)
后续只需要动态创建 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 标签或者点击"搜索一下"跳转百度进行搜索时,利用事件冒泡原理,进行事件委托。这里没有考虑兼容性问题:
1
2
|
e = e || window.event; target = e.target || e.srcElement; |
6.除了点击事件,键盘事件–回车键以及上下键都是进行事件委托进行注册的。
最终能够实现键盘上下键鼠标选择,点击“搜索一下”或回车键实现跳转搜索。
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
|
<!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 > |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/rujin_shi/article/details/83657566