前言:
最近有個輸入框自動補全的需求,例如百度搜索功能:前端
在輸入框輸入信息後,自動提示補全。我選擇用typeahead.js,後來發現,原來這個庫的相關學習資料不多,搞的稍微有點久,才弄明白點...
本文實屬原創,若有錯誤,敬請指教!jquery
簡介:git
官網:http://twitter.github.io/typeahead.js
github: https://github.com/twitter/typeahead.js
使用文檔:https://www.awesomes.cn/repo/twitter/typeahead-jsgithub
在查資料的過程當中,不難發現,typeahead.js一直會跟boostrap扯上關係。實際上在bootstrap 2.x時,自帶了補全控件typeahead;可是到了,bootstrap 3.x時,捨棄了這個插件,這是出現了單獨插件,名叫bootstrap-3-typeahead,再後面bootstrap-3-typeahead 更名 typeahead.js.ajax
實踐:正則表達式
由於typeahead的更新變更老是很大,因此每一個版本的改動也很大,而typeahead因此依賴的庫也出現了稍微的變化。下面介紹兩種方法:
第一個bower安裝,也是比較能保證依賴文件的準確性:json
在項目裏面
$ bower install typeahead.js
bootstrap
第二種手動引用:
先下載最新版的typeahead.js,以及全部相關依賴。點我點我下載~
下載後,會是下面這幾個文件:數組
詳解:緩存
bloodhound.js(獨立建議引擎)
typeahead.jquery.js(獨立的typeahead庫)
typeahead.bundle.js(bloodhound+typeahead.jquery的組合體)
注:bloodhound.js和typeahead.jquery.js對jQuery 1.9+依賴。
Examples:
一、基礎示例
Html代碼:
<div class="example"> <h2>基本示例</h2> <div id="basic-example"> <input class="typeahead" type="text" placeholder="請輸入省份"> </div> </div>
js代碼:
jQuery(function () { /*** 1.基本示例 ***/ var provinces = ["廣東省", "海南省", "山西省", "山東省","湖北省", "湖南省", "陝西省", "上海市", "北京市", "廣西省"]; var substringMatcher = function (strs) { return function findMatches(q, cb) { var matches, substrRegex; matches = [];//定義字符串數組 substrRegex = new RegExp(q, 'i'); //用正則表達式來肯定哪些字符串包含子串的'q' $.each(strs, function (i, str) { //遍歷字符串池中的任何字符串 if (substrRegex.test(str)) { matches.push({ value: str }); } //包含子串的'q',將它添加到'match' }); cb(matches); }; }; $('#basic-example .typeahead').typeahead({ highlight: true, minLength: 1 }, { name: 'provinces', displayKey: 'value', source: substringMatcher(provinces) }); });
效果圖下(請忽略醜醜的UI):
數據爲:
var provinces = ["廣東省", "海南省", "山西省", "山東省","湖北省", "湖南省", "陝西省", "上海市", "北京市", "廣西省"];
---------- 華麗麗的分割線 ----------
下面爲要介紹兩種用ajax獲取遠程數據的模式:
第一種是prefetch,是對數據請求一次,把全部數據拿下來。
第二種是remote,只有當觸發輸入框的時候,數據才從服務端獲取。
二、ajax數據預讀示例(prefetch)
Html代碼爲:
<div class="example"> <h2>Ajax數據預讀示例</h2> <div id="ajax-prefetch-example"> <input class="typeahead" type="text" placeholder="請輸入省份"> </div> </div>
JS代碼爲:
/*** 2.Ajax數據預讀示例 ***/ // 遠程數據源 var prefetch_provinces = new Bloodhound({ datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'), queryTokenizer: Bloodhound.tokenizers.whitespace, // 預獲取並緩存 prefetch: '././data/provinces.json' }); prefetch_provinces.initialize(); $('#ajax-prefetch-example .typeahead').typeahead({ hint: true, highlight: true, minLength: 1 } , { name: 'provinces', displayKey: 'value', source: prefetch_provinces.ttAdapter() });
數據爲:
[ { "Id":1, "value": "廣東省" }, { "Id":2, "value": "海南省" }, { "Id":3, "value": "山西省" }, { "Id":4, "value": "山東省" }, { "Id":5, "value": "湖北省" }, { "Id":6, "value": "湖南省" }, { "Id":7, "value": "陝西省" }, { "Id":8, "value": "上海市" }, { "Id":9, "value": "北京市" }, { "Id":10, "value": "廣西省" } ]
文件結構爲:
效果以下:
這時候咱們發現了一個問題,當你輸入一個「海」字,是否還能跟示例1同樣,出現「海南省」和「上海市」呢?答案看圖:
結果是不能!!
爲何呢??哈哈~由於相比示例1,示例2沒有嚴謹的正則表達式再作篩選,改進方法是本身再添加多一個正則判斷!
3.Ajax及時獲取數據示例(remote)
Html代碼:
<div class="example"> <h2>Ajax及時獲取數據示例</h2> <div id="ajax-remote-example"> <input class="typeahead" type="text" placeholder="請輸入城市"> </div> </div>
JS代碼爲:
/*** 3.Ajax及時獲取數據示例 ***/ //遠程數據源 var remote_cities = new Bloodhound({ datumTokenizer: Bloodhound.tokenizers.obj.whitespace('CityName'), queryTokenizer: Bloodhound.tokenizers.whitespace, // 在文本框輸入字符時才發起請求 remote: '././ajax/GetCities?q=%QUERY' }); remote_cities.initialize(); $('#ajax-remote-example .typeahead').typeahead({ hint: true, highlight: true, minLength: 1 }, { name: 'cities', displayKey: 'CityName', source: remote_cities.ttAdapter(), });
數據爲:
[{"Id":1,"ProvinceName":"廣東省","CityName":"廣州市"},{"Id":2,"ProvinceName":"山東省","CityName":"濟南市"},{"Id":3,"ProvinceName":"陝西省","CityName":"西安市"},{"Id":4,"ProvinceName":"北京市","CityName":"北京市"},{"Id":5,"ProvinceName":"廣西自治區","CityName":"南寧市"},{"Id":6,"ProvinceName":"江蘇省","CityName":"南京市"}]
文件結構爲:
效果圖爲:
看到這裏應該有很多人有疑問吧?爲何輸入「南」字,雖然與「南」相關的數據都有匹配到,可是全部數據都出來了?這是爲何呢?
答案有點繞,首先,咱們要清楚一點,remote的方法是當你觸發事件後,纔想遠程及時獲取數據的,可是示例3所有用到的是前端的東西,只是模擬從遠程拿取數據,並無從真正的服務器上面獲取,因此結果就是顯示全部數據(個人錯!哈哈哈),解決方法就是:在服務端加多一個正則加以過濾,只有匹配到的纔拿下來。雖說前端也是能夠作過濾的,可是儘可能不要把沒必要要的數據下載下來。
有些同窗可能會問了,示例2和示例3的數據匹配方式好像不一樣耶?爲何同一個庫示例2匹配只從頭開始,而示例3則是任意文字匹配呢?
答案:由於在typeahead裏面prefetch和remote封裝的方法不一樣。詳情能夠查看typeahead裏面的源碼。
接口:
name —— 數據集的名字。
source —— 規定包含查詢時要顯示的值的數據源。值的類型是 array,默認值是 [ ]。
items —— 規定查詢時要顯示的條目的最大值。數據類型是 number,默認值是 8。
highlighter —— 用於自動高亮突出顯示結果。帶有一個單一的參數,即具備 typeahead 實例範圍的條目。數據類型是 function。默認狀況下是高亮突出顯示全部默認的匹配項。
minLength —— 推薦引擎開始渲染所須要的最小字符。默認爲 1 。
hint —— 默認爲 true,會自動補全第一個匹配的元素,設置爲 false 時,typeahead 將不會補全 .
display - 對於推薦對象,決定用何種字符串表示,並將會在某個輸入控件選擇後使用。其值能夠是關鍵字符串,或者是將推薦對象轉換爲string的函數。默認爲 value.
$('.typeahead').typeahead('destroy');移除typeahead功能,並將 input 元素的狀態重置爲原始狀態。
$('.typeahead').typeahead('open');打開typeahead下拉菜單。
$('.typeahead').typeahead('close');關閉typeahead的下拉菜單。
var myVal = $('.typeahead').typeahead('val'); 返回typeahead的當前值,該值爲用戶輸入到 input 元素中的文本
$('.typeahead').typeahead('val', myVal);設置typeahead的值,要來替代 jQuery#val 函數。
實屬原創,若有錯誤,煩請指教!