搜索功能的實現

在愛課幫http://www.ikebang.com的項目當中,需要新增加一個搜索功能,剛接到這個任務的時候頭都大了,以前從來沒有做過。但是辦法總是想出來的,只好慢慢的做了。

主要技術

  1. 前端:jQuery、seajs
  2. 後臺:php

遇到的問題

  1. 通過上下鍵來選擇列表內容
  2. 失焦(列表會隱藏)如何在點擊列表中的每一項
  3. 如何避免頻繁的向後臺請求數據(減少後臺的壓力)

效果圖如下(背景圖爲canvas有些失真):
這裏寫圖片描述

開始上代碼了

css代碼如下:

<input type="text" class=" global-search js-global-serach "placeholder="請輸入搜索內容" value="">
    <i class="imv2-search search-logo js-search-logo"></i>
    <ul class="search-list js-search-list" >

    </ul>

主要功能代碼如下:

//第一個問題上下鍵控制
 $(document).on("keyup",".js-global-serach",function(e){
            //阻止事件的冒泡傳播,使光標始終停留在文本區最後面
            e.stopPropagation();

            //找到下拉列表中的具有cur類的li的數量如果沒有的話,返回-1,有的話獲取當前具有cur類li相對於同級元素的索引值
            var curIndex = $('.js-search-list li.cur').size() > 0 ? $('.js-search-list li.cur').index() : -1;
            if(e.keyCode==13){
                var item=$.trim($(this).val())
                if(item){
                    bindEventFuns.startSearch(item);
                }

            }
            //上鍵控制
            if(e.keyCode==38){  
                if(curIndex > 0){
                    $('.js-search-list li').eq(curIndex - 1).addClass('cur').siblings('li').removeClass('cur');
                    //沒有的話,讓列表中的第一個元素選中
                }else if(curIndex == -1){
                    $('.js-search-list li').eq(0).addClass('cur');
                }else{
                //第一個選中,如果在按上鍵的時候應該爲最後一個選中,此時curIndex的值爲0
                    $('.js-search-list li').eq($('.js-search-list li').size() - 1).addClass('cur').siblings('li').removeClass('cur');
                }

                var inputVal = $('.js-search-list li.cur').text();
                $(this).val(inputVal);
            }
            //下鍵控制
            if(e.keyCode==40){
                if(curIndex == -1){
                    $('.js-search-list li').eq(0).addClass('cur');
                }else if(curIndex < $('.js-search-list li').size() - 1){
                    $('.js-search-list li').eq(curIndex + 1).addClass('cur').siblings('li').removeClass('cur');
                }else{
                    $('.js-search-list li').eq(0).addClass('cur').siblings('li').removeClass('cur');
                }

                $(this).val($('.js-search-list li.cur').text());
            }
        })

第二個問題:

$(document).on("mousedown",".js-search-list li",function(e){
            var item=$.trim($(this).text())
            //被點擊的哪項存在,且不爲鼠標右鍵的時候,纔會發生跳轉
            if(item && e.button!=2){
                bindEventFuns.startSearch(item);
            }
        })

本來自己寫的時候是用的click事件,但是當觸發input框的blur事件被觸發的時候,列表就會隱藏了,導致無法點擊。在網上看到了一種解釋:

鼠標的click事件可以分爲鼠標按下按鼠標擡起

看到這就話是我的腦洞瞬間被打開了,那就用onmousedown來解決,試驗了之後發現非常完美。事件之間的互斥性也解決了,啦啦啦!

然而當我用鼠標右鍵點擊的時候它還能跳轉,這個就尷尬了,趕快找了下:
event.button

button 事件屬性可返回一個整數,指示當事件被觸發時哪個鼠標按鍵被點擊

event.button=0|1|2
//0 :代表的爲點擊鼠標左鍵
//1 :代表點擊的爲鼠標中間鍵
//2 :代表點擊的爲鼠標右鍵

到此問題2已經解決了。

最後的問題如何解決頻繁的向後臺發送請求,首先想到的是使用定時器,但是定時器只是延遲發送了,實際上還是發送請求了,並沒有從根本上解決問題。

這時就在網絡的中開始查找了,最終找到了一個相當好的方法,那就是利用event.timeStamp
官方文檔的解釋:

該屬性可用於通過獲取event.timeStamp代碼中兩點的值並分析差異來分析事件性能(這就話話就有點6了,也沒做深入的理解,反正確實有這樣的效果)。要簡單地確定事件處理程序中的當前時間,請(new Date).getTime()改爲使用。

//定義一個全局變量
var lastTime;

//查找方法如下:
  searchShow:function(e){
            //獲取改變的時間戳
            lastTime=e.timeStamp;
            var searchContent=$.trim($(this).val());

            //爲空列表隱藏
            if(searchContent==""){
                $(".js-search-list").hide();
            }
            //只有輸入內容不爲空的話發送請求
            else{
                setTimeout(function () {
                    if(lastTime-e.timeStamp==0){
                    $.ajax({
                        url:"/search/getsearchword",
                        data:{
                            word:searchContent
                        },
                        datatype:"json",
                        method:"get",
                        success:function(res){
                            var res=JSON.parse(res);
                            if(res.result==1){
                                //如果聯想詞沒有數據的話,什麼也不做
                                console.log(res.data)
                                if(res.data.length==0){
                                    $(".js-search-list").hide();
                                    return;
                                }
                                else{
                                //es6字符串拼接
                                    var connectList=res.data;
                                    var str=``;
                                    for (var index = 0; index < connectList.length; index++) {
                                       str+=`<li>${connectList[index]}</li>`
                                    }
                                    console.log(str);
                                    $(".js-search-list").html(str);
                                    $(".js-search-list").slideDown("fast");
                                }
                          }

                        }                  
                    })}
                }, 250);

            }
            },
            //判斷用戶來源地址
          startSearch:function(item){
              if(rel_page=="resource"||rel_page=="col_resource"){
                  window.location.href="/search/resource?words="+item;
                  return;
              }
              else if(rel_page=="qa"||rel_page=="answer"||rel_page=="col_question"||rel_page=="bookqa"||rel_page=="bookwaitreply"||rel_page=="lessonqa"||rel_page=="lessonwaitreply"){
                window.location.href="/search/qa?words="+item;
                return;
              }
              else if(rel_page=="lesson"||rel_page=="col_lesson"){
                window.location.href="/search/lesson?words="+item;
                return;
              }
              else if(rel_page=="designlist"||rel_page=="col_designlist"||rel_page=="design"){
                window.location.href="/search/design?words="+item;
                return;
              }
              else{
                window.location.href="/search/index?words="+item;
                $(".js-search-tool").val(item);
              }

        }  

注意:由於自2004年以來開放的錯誤,該值在Firefox中未正確填充,因此無法知道在該瀏覽器中創建事件的時間
jq api 官網:https://api.jquery.com/event.timeStamp/

至此,在開發搜索工程中遇到的問題基本上已經解決了,在這個工作中也學到了很多的東西。最重要的一點就是在寫代碼之前,一定要把邏輯弄清楚了這樣纔會事半功倍

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章