首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

AJAX 自動完成下拉選單:輸入即時搜尋與鍵盤導航完整實作

     編輯:更多程式設計知識

Google 搜尋框、電商關鍵字聯想皆為經典「自動完成」體驗。本文實作一個具備防抖、快取、鍵盤選取、滑鼠點選、多輸入框共存的完整元件,後端以 JSON 回傳資料,前端原生 JS + jQuery 渲染。

HTML 結構

<input type="text" id="brandName" autocomplete="off">
<input type="hidden" id="brandId">
<div class="autocomplete-wrap" id="brandList">
  <ul class="autocomplete-list" id="brandListUl"></ul>
</div>

CSS 關鍵:.autocomplete-wrap { position:absolute; display:none; border:1px solid #ccc; background:#fff; z-index:999; },ul { max-height:200px; overflow-y:auto; }。

JavaScript 核心邏輯

var AC = (function($) {
  var cache = {}, xhrPool = {};

  function fetch(listId, inputId, hiddenId, apiUrl, kw) {
    if (xhrPool[listId]) xhrPool[listId].abort(); // 取消前一次請求
    if (cache[kw]) return render(listId, inputId, hiddenId, cache[kw]);

    xhrPool[listId] = $.getJSON(apiUrl, { keyword: kw, _: Date.now() }, function(data) {
      cache[kw] = data;
      render(listId, inputId, hiddenId, data);
    });
  }

  function render(listId, inputId, hiddenId, data) {
    var $ul = $('#' + listId + 'Ul').empty();
    $.each(data, function(i, item) {
      $('
  • ').text(item.name) .data('id', item.id) .on('mousedown', function() { $('#' + inputId).val(item.name); $('#' + hiddenId).val(item.id); hide(listId); }) .appendTo($ul); }); show(listId); } function show(id) { $('#' + id).show(); } function hide(id) { $('#' + id).hide(); } return { bind: function(inputId, hiddenId, listId, apiUrl, delay) { var $inp = $('#' + inputId), timer; $inp.on('input', function() { clearTimeout(timer); var kw = $.trim(this.value); timer = setTimeout(function() { if (kw) fetch(listId, inputId, hiddenId, apiUrl, kw); else hide(listId); }, delay || 200); }); $inp.on('focus', function() { if ($.trim(this.value)) fetch(listId, inputId, hiddenId, apiUrl, $.trim(this.value)); }); $(document).on('mousedown', function(e) { if (!$(e.target).closest('#' + listId + ', #' + inputId).length) hide(listId); }); // 鍵盤上下選取、Enter 確認、Esc 關閉 $inp.on('keydown', function(e) { var $ul = $('#' + listId + 'Ul'), $lis = $ul.children('li'), $sel = $ul.children('.active'); if (e.keyCode === 40) { // Down e.preventDefault(); var $next = $sel.length ? $sel.next() : $lis.first(); $sel.removeClass('active'); $next.addClass('active'); } else if (e.keyCode === 38) { // Up e.preventDefault(); var $prev = $sel.length ? $sel.prev() : $lis.last(); $sel.removeClass('active'); $prev.addClass('active'); } else if (e.keyCode === 13) { // Enter $sel.mousedown(); } else if (e.keyCode === 27) { // Esc hide(listId); } }); } }; })(jQuery); // 使用範例 $(function() { AC.bind('brandName', 'brandId', 'brandList', '/api/brands', 200); AC.bind('seriesName', 'seriesId', 'seriesList', '/api/series', 200); });
  • 後端 API 規範

    請求:GET /api/brands?keyword=寶馬&_=1623456789

    回應:[{"id":"1","name":"寶馬"},{"id":"2","name":"寶馬X5"}]

    效能與體驗優化清單

    • 防抖:setTimeout 延遲 200ms 送請求,避免每按鍵即發送。
    • 請求取消:新請求前 abort() 舊請求,避免競態條件導致舊資料覆蓋新資料。
    • 前端快取:同關鍵字二次輸入直接讀 cache[kw],零延遲。
    • 鍵盤無障礙:上下鍵選取、Enter 確認、Esc 關閉,符合 WAI-ARIA 建議(可再加 role="listbox", aria-activedescendant)。
    • 點擊外部關閉:document.mousedown 判斷目標是否在下拉區或輸入框內。
    • 多實例隔離:模組化封裝,同頁可掛載多組自動完成互不干擾。
    1. 上一篇文章:
    2. 下一篇文章:
    Copyright © 程式碼之家 All Rights Reserved