案例:搜索框內容自動提示


實現功能如下:

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>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM