本文實例為大家分享了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