實現功能如下:
1. 獲取搜索框並為其添加用戶輸入事件
2. 獲取用戶輸入的關鍵字
3. 向服務器端發送請求並攜帶關鍵字作為請求參數
4. 將響應數據顯示在搜索框底部
搜索框輸入自動提示接口:
- 簡要描述
- 根據用戶在文本框中輸入的關鍵字,匹配相關內容
- 請求地址
- /searchAutoPrompt
- 請求方式
- GET
- 參數
參數名 | 必選 | 類型 | 說明 |
key | 是 | string | 用戶輸入的關鍵字 |
- 返回值
[ 'ajax同步異步', 'ajax教程', '$.ajax()方法詳解' ]
該案例有個問題:比如說輸入Ajax
第一次發送請求的時候攜帶的參數是A
第二次發送請求的時候攜帶的參數是AJ
第三次發送請求的時候攜帶的參數是AJA
即使使用的是中文輸入法,在輸入拼音的時候,拼音也被發送到了服務器端,這是不合理的,這無形當中發送了很多無意義的請求
如何保證在用戶輸入完成之后,再向服務器端發送請求呢?
在用戶連續輸入的情況下,輸入字符的速度是比較快的,兩個字符之間的時間間隔是比較短的,我們可以利用這個時間間隔來解決這個問題。
具體怎么做呢?
在oninput事件觸發的時候,在請求的外部包裹一層延遲定時器,讓請求不要立即發送。
由於用戶是連續輸入,oninput事件會被不斷觸發。當再一次觸發oninput事件的時候,先將上一次開啟的延遲定時器清除,定時器清除了請求也就不會發送,這就保證了上一次的輸入不會有請求發送。然后再開啟一個新的定時器,用於當前這一次的輸入發送請求。循環往復,直到用戶輸入完成才會發送一次請求。實際上,每次的輸入都會清除上一次的定時器,這就大大減少了無意義請求的次數。
第二個問題:當我們把搜索框中的文字清除掉的時候,下面的相關內容並沒有被清空,但實際上搜索提示框是不應該顯示的。
解決方案:當搜索框的內容為空時,隱藏提示框。
<!-- 引入bootstrap樣式文件 --> <link rel="stylesheet" href="/assets/bootstrap/dist/css/bootstrap.min.css"> <!-- css樣式 --> <style type="text/css"> .container { padding-top: 150px; } .list-group { display: none; } </style>
<!-- 頁面布局 --> <div class="container"> <div class="form-group"> <input type="text" class="form-control" placeholder="請輸入搜索關鍵字" id="search"> <ul class="list-group" id="list-box"> </ul> </div> </div>
引入自己封裝好的ajax.js文件:
<script type="text/javascript"> function ajax (options) { // 存儲的是默認值 var defaults = { type: 'get', url: '', data: {}, header: { 'Content-Type': 'application/x-www-form-urlencoded' }, success: function () {}, error: function () {} }; // 使用options對象中的屬性覆蓋defaults對象中的屬性 Object.assign(defaults, options); // 創建ajax對象 var xhr = new XMLHttpRequest(); // 拼接請求參數的變量 var params = ''; // 循環用戶傳遞進來的對象格式參數 for (var attr in defaults.data) { // 將參數轉換為字符串格式 params += attr + '=' + defaults.data[attr] + '&'; } // 將參數最后面的&截取掉 // 將截取的結果重新賦值給params變量 params = params.substr(0, params.length - 1); // 判斷請求方式 if (defaults.type == 'get') { defaults.url = defaults.url + '?' + params; } /* { name: 'zhangsan', age: 20 } name=zhangsan&age=20 */ // 配置ajax對象 xhr.open(defaults.type, defaults.url); // 如果請求方式為post if (defaults.type == 'post') { // 用戶希望的向服務器端傳遞的請求參數的類型 var contentType = defaults.header['Content-Type'] // 設置請求參數格式的類型 xhr.setRequestHeader('Content-Type', contentType); // 判斷用戶希望的請求參數格式的類型 // 如果類型為json if (contentType == 'application/json') { // 向服務器端傳遞json數據格式的參數 xhr.send(JSON.stringify(defaults.data)) }else { // 向服務器端傳遞普通類型的請求參數 xhr.send(params); } }else { // 發送請求 xhr.send(); } // 監聽xhr對象下面的onload事件 // 當xhr對象接收完響應數據后觸發 xhr.onload = function () { // xhr.getResponseHeader() // 獲取響應頭中的數據 var contentType = xhr.getResponseHeader('Content-Type'); // 服務器端返回的數據 var responseText = xhr.responseText; // 如果響應類型中包含applicaition/json if (contentType.includes('application/json')) { // 將json字符串轉換為json對象 responseText = JSON.parse(responseText) } // 當http狀態碼等於200的時候 if (xhr.status == 200) { // 請求成功 調用處理成功情況的函數 defaults.success(responseText, xhr); }else { // 請求失敗 調用處理失敗情況的函數 defaults.error(responseText, xhr); } } } ajax({ type: 'post', // 請求地址 url: 'http://localhost:3000/responseData', success: function (data) { console.log('這里是success函數'); console.log(data) } }) /* 請求參數要考慮的問題 1.請求參數位置的問題 將請求參數傳遞到ajax函數內部, 在函數內部根據請求方式的不同將請求參數放置在不同的位置 get 放在請求地址的后面 post 放在send方法中 2.請求參數格式的問題 application/x-www-form-urlencoded 參數名稱=參數值&參數名稱=參數值 name=zhangsan&age=20 application/json {name: 'zhangsan', age: 20} 1.傳遞對象數據類型對於函數的調用者更加友好 2.在函數內部對象數據類型轉換為字符串數據類型更加方便 */ </script>
<script src="/js/ajax.js"></script> <!-- 引入下載好的模板引擎文件, 下載網址:https://aui.github.io/art-template/zh-cn/index.html --> <script src="/js/template-web.js"></script> <!-- 模板 --> <script type="text/html" id="tpl"> {{each result}} <li class="list-group-item">{{$value}}</li> {{/each}} </script>
<!-- JS邏輯代碼 --> <script> // 獲取搜索框 var searchInp = document.getElementById('search'); // 獲取提示文字的存放容器 var listBox = document.getElementById('list-box'); // 存儲定時器的變量 var timer = null; // 當用戶在文本框中輸入的時候觸發 searchInp.oninput = function () { // 清除上一次開啟的定時器 clearTimeout(timer); // 獲取用戶輸入的內容 var key = this.value; // 如果用戶沒有在搜索框中輸入內容 if (key.trim().length == 0) { // 將提示下拉框隱藏掉 listBox.style.display = 'none'; // 阻止程序向下執行 return; } // 開啟定時器 讓請求延遲發送 timer = setTimeout(function () { // 向服務器端發送請求 // 向服務器端索取和用戶輸入關鍵字相關的內容 ajax({ type: 'get', url: 'http://localhost:3000/searchAutoPrompt', data: { key: key }, success: function (result) { // 使用模板引擎拼接字符串 var html = template('tpl', {result: result}); // 將拼接好的字符串顯示在頁面中 listBox.innerHTML = html; // 顯示ul容器 listBox.style.display = 'block'; } }) }, 800) } </script>