首頁  >  文章  >  web前端  >  input輸入框的自動比對(原生程式碼)_javascript技巧

input輸入框的自動比對(原生程式碼)_javascript技巧

WBOY
WBOY原創
2016-05-16 17:40:041808瀏覽

今天看群組裡有人發起了人人網以前一些面試題,我以前也轉載過一些,恰好閒著,挑選一題來做做,練個手。

本題有以下要求
1. 使用原生程式碼實現,不可使用任何框架;
2. 對input框中輸入的字元進行匹配,將匹配到的內容以選單的形式展現在input框的下方;
3. 只針對英文字元進行匹配,並且匹配到的內容在選單中加粗;
4. 透過鍵盤上的上下箭頭可以對選單進行選擇,按下回車後將選取的內容寫入到input框中;
思路
捕捉輸入變化,用使用者輸入的值(下稱輸入值)去匹配列表項,這裡假設列表項是查詢傳回的一個數組(下稱列表),匹配方式為用輸入值作為開始值來匹配每個列表值,將符合篩選條件的項輸出到頁面。
分 析
第三點要求中關鍵字是加粗,這裡用正規替換就好了。
第四點要求的關鍵字就比較多了,一句話暗藏許多殺機,這一部分主要是針對鍵盤,首先是上下按鍵,然後是回車,還有一個寫入到input框。

到這,如果你認為完了那就操之過急了,至少還有4個隱性的需求。
•第一項預設高亮顯示,上下按鍵的同時當前項高亮。
•按Enter預設第一項被選取。
•老鼠經過時當前項高亮。
•支援點選選取項目。
也許還有遺漏,這裡就不糾結了。
實 踐
這雖然是一道JS題,但這之前,頁面結構還是要先寫好。

複製程式碼 程式碼如下:










由於不允許用框架,這裡對一些可能要到的方法作一個簡單的封裝。 先建立一個封裝對象,暫且取名 dom,接下來的原生方法都放進這個物件以作複用。 複製程式碼

程式碼如下:


var dom = { <. f5>$ : function( ){
return document.getElementById(id);
},
tag : function( tagName,root ){
root = root ? root : document;
return this.rootmakeArray(t. 。
}else if( document.attachEvent ){
element.attachEvent( 'on' type,handler );
};
},
removeClass : function( list,name ){
var el = list[i],
r = new RegExp('\s*\b' name '\b\s*','g');
for( var i = 0 , len = list.length ; i var cur = list[i];
if( r.test( cur.className ) ){
cur.className = cur.className.replace (r,'');
};
};
},
height : function( element ){
return element.offsetHeight;
},
getBound : function( element ){
return element.getBoundingClientRect();
},
getText : function( element ){
return element.textContent ? element.textContent Text:ementel. ,
trim : function( string ){
return string.replace( /^s*(.*)s*$/,'$1' );
},
makeArray : function( tag ){
for( var i = 0 , arr = [] , len = tagList.length ; i arr.push( tagList[i] );
};
};
return arr;
},
isVisible : function( element ){
return element.style.display == 'block';
}
};



接著再創建一個對象,用來存放具體的處理邏輯,作者英文比較狗血,就叫autoMatch吧。
這個物件要做的事情可多了:
•確定好選單的位置;
•即時處理使用者輸入;
•處理滑鼠和鍵盤按鍵動作;
決定選單的位置用封裝對象dom的getBound方法,傳回一個邊界對象,此物件有兩個屬性left和top。眼熟吧,它類似jQuery裡的offset()方法。
處理使用者輸入這裡值得一提,由於是即時處理,開始考慮用onchange事件,但是它只會在失去焦點時才觸發,所以是不合理的。
這時我的目光轉向了oninput,它完全能夠勝任工作。
複製程式碼 程式碼如下:

dom.bind( obj.input,'obj.input,' this.inputProcess );

可是,IE又做了一回不走尋常路的事兒。它並不支援oninput。
空歡喜一場,白瞎了!
凡事總是有轉機的。角落裡的onpropertychange向我們緩緩走來…,它和oninput非常相似,有著一樣的特性,至少在捕捉input輸入方面,正是我想要的,對付IE,我們都用它,用了都說好。
再綁定一次:
複製程式碼 程式碼如下:
. obj.input,'propertychange' , this.inputProcess );

接下來是按鍵,上,下,回車。對應的鍵編碼分別是38、40、13,唯一要注意的是FF和IE的屬性名稱不一樣。
詳細的實作細節請見Demo:

猛擊我查看Demo 真實業務場景中,可能要對用戶的輸入作實時Ajax查詢,這代表著每敲一個字母都會有查詢一次。
然而如此頻繁發送Ajax請求實在太不划算,回應速度上也不容許這樣的實現。
我的想法是當使用者敲第一個字母時,發送一次請求(請求資料一般有數量限制,一般是10條),並將回傳值儲存起來(下稱快取)。
在第一個字母之後的使用者輸入,都在快取裡面篩選,到這裡就如同本地查詢一樣了,每輸入一個字母,精確度越來越高,快取越來越小。
當使用者清空,重新輸入時重複以上的步驟。
當然,不排除會有一些更複雜的業務場景,例如,在匹配充足的情況下,要保證用戶每次輸入都有10條資料可選,這就需要更多的判斷以及請求。
所以,具體實作取決於真實的業務場景。
至此,本文結束。感謝閱讀,歡迎有血有肉的置評。
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn