typeahead.js 的 jQuery 插件 API 完全指南:用法、选项、数据集与自定义事件
【免费下载链接】typeahead.jstypeahead.js is a fast and fully-featured autocomplete library项目地址: https://gitcode.com/gh_mirrors/ty/typeahead.js
typeahead.js 的 UI 组件以 jQuery 插件的形式对外提供,负责渲染建议列表并处理所有 DOM 交互(输入、键盘、鼠标、焦点等)。本文以官方文档 doc/jquery_typeahead.md 为主体,结合 src/typeahead/plugin.js、src/typeahead/typeahead.js、src/typeahead/dataset.js 等源码,系统讲解插件的初始化 API、全部可配置选项、数据集(Dataset)机制、自定义事件与类名覆盖方案,帮助你在页面中快速接入并深度定制自动补全能力。
特性一览
typeahead.js 的 jQuery 插件提供以下开箱即用的能力:
- 实时建议展示:用户输入过程中即时渲染建议列表;
- Hint 提示:将最佳建议作为背景文字显示在输入框内(即"背景文本"效果);
- 自定义模板:通过
templates配置完全掌控建议的渲染方式,支持 UI 灵活性; - RTL 与输入法友好:原生支持从右到左的语言方向,并兼容输入法编辑器(IME);
- 查询高亮:在建议文本中高亮当前查询的匹配片段;
- 自定义事件:暴露一系列
typeahead:前缀事件,方便扩展与集成。
其中 Hint 与高亮的底层实现在 src/typeahead/input.js 与 src/typeahead/highlight.js 中,RTL 方向检测则由 src/typeahead/input.js 的_checkLanguageDirection完成。
快速上手:初始化插件
插件挂载在jQuery.fn.typeahead上。对于一个input[type="text"]元素,调用$('.typeahead').typeahead(options, [*datasets])即可启用 typeahead 功能:
options是配置哈希,用于整体行为配置(详见下文 Options);- 之后的参数(
*datasets)是零个或多个数据集配置哈希(详见下文 Datasets)。
$('.typeahead').typeahead({ minLength: 3, highlight: true }, { name: 'my-dataset', source: mySource });在源码层面,初始化逻辑位于 src/typeahead/plugin.js 的initialize方法。该方法会依次完成以下组装工作:
- 将顶层
highlight配置继承给每一个数据集(_.each(datasets, function(d) { d.highlight = !!o.highlight; });); - 根据
hint与menu选项决定是否自动创建 hint 输入框和菜单节点,若hint !== false且未显式传入 hint 元素,则通过buildHintFromInput克隆原输入框生成只读的 hint 层; - 将输入框包装进
.twitter-typeahead容器,并把 hint、menu 插入其中; - 依次实例化
EventBus、Input、Menu(或DefaultMenu)与核心Typeahead,最后把实例通过$input.data('tt-typeahead', ...)保存在输入框上。
值得一提的是,初始化还支持传入数据集数组形式:$('#el').typeahead(options, [dataset1, dataset2])。源码通过_.isArray(datasets) ? datasets : [].slice.call(arguments, 1)兼容两种传参方式。
完整 API 参考
除了初始化,插件还提供多个命令式方法,均以$('.typeahead').typeahead('methodName', ...)的形式调用。插件分发逻辑在 src/typeahead/plugin.js 末尾:若第一个参数是已注册的方法名则调用对应方法,否则视为初始化调用。
jQuery#typeahead('val')
读取当前 typeahead 的值(即用户在input中输入的文字):
var myVal = $('.typeahead').typeahead('val');实现上,val读取操作只作用于集合中的第一个元素(ttEach(this.first(), ...)),最终返回Typeahead#getVal()(见 src/typeahead/typeahead.js),即input.getQuery()。
jQuery#typeahead('val', val)
设置 typeahead 的值。官方明确建议用此方法替代jQuery#val:
$('.typeahead').typeahead('val', myVal);与读取不同,写入操作会作用于集合中的所有元素,内部调用Typeahead#setVal(val),它会先把值强制转为字符串再交给input.setQuery,因此传数字等非字符串值也能安全处理。
jQuery#typeahead('open') 与 jQuery#typeahead('close')
手动打开 / 关闭建议菜单:
$('.typeahead').typeahead('open'); $('.typeahead').typeahead('close');注意,open会依次经过eventBus.before('open')(可被阻止)、menu.open()、_updateHint()与eventBus.trigger('open');close则额外会清除 hint 并将输入值重置为当前 query(见 src/typeahead/typeahead.js 的close方法)。
jQuery#typeahead('destroy')
移除 typeahead 功能,并把input元素恢复为原始状态:
$('.typeahead').typeahead('destroy');销毁过程在 src/typeahead/plugin.js 的revert函数中完成:它会恢复初始化时被改动的dir、autocomplete、spellcheck、style等属性(这些原始值在初始化时通过prepInput存入data('tt-attrs')),移除.tt-input类,解绑事件并拆掉包装容器。测试用例可见 test/typeahead/plugin_spec.js。
jQuery.fn.typeahead.noConflict()
返回 typeahead 插件的引用,同时把jQuery.fn.typeahead还原为之前的值,用于避免命名冲突:
var typeahead = jQuery.fn.typeahead.noConflict(); jQuery.fn._typeahead = typeahead;源码实现非常简洁(src/typeahead/plugin.js):
$.fn.typeahead.noConflict = function noConflict() { $.fn.typeahead = old; // old 在插件加载时被保存为原来的 $.fn.typeahead return this; };选项(Options)详解
初始化 typeahead 时可配置以下整体选项:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
highlight | boolean | false | 为true时,渲染建议时当前 query 在文本节点中的匹配片段会被包裹在strong元素中,其 class 为{{classNames.highlight}} |
hint | boolean | true | 为false时不显示 hint(背景建议文本) |
minLength | number | 1 | 触发建议渲染所需的最小输入字符长度 |
classNames | object | — | 覆盖默认 class 名,详见下文 Class Names |
menu | jQuery/Element | — | 显式传入菜单 DOM 节点;false可禁用默认菜单的自动创建 |
dataset相关 | — | — | 数据集级配置,见下文 Datasets |
几点源码层面的补充说明:
minLength在 src/typeahead/typeahead.js 构造函数中被规范化:this.minLength = _.isNumber(o.minLength) ? o.minLength : 1。查询长度是否达标由_minLengthMet(query)判断,未达标时会清空菜单而不是渲染建议。highlight是顶层配置,会在初始化时被强制注入每个数据集(d.highlight = !!o.highlight),因此即使数据集自身没写highlight,也会继承顶层设置。menu与hint选项还可以直接传入已有的 jQuery 对象或 DOM 元素,此时插件复用该节点而不再自动创建(见 src/typeahead/plugin.js 的$elOrNull函数)。
数据集(Datasets)机制
一个 typeahead 由一个或多个数据集组成。当用户修改输入值时,每个数据集都会针对新值尝试渲染建议。对大多数场景而言,一个数据集就足够了;只有在希望建议按某种分类关系分组展示时才需要多个数据集。例如 twitter.com 的搜索框会把结果分为"最近搜索、热门话题、用户账号"几组——这正是多数据集的典型用例。
多个数据集会渲染在同一菜单容器内,每个数据集独占一个带tt-dataset-<name>class 的 DOM 节点,组间天然形成视觉分组。
source(必填)
数据集的底层数据源。期望是一个签名为(query, syncResults, asyncResults)的函数:
syncResults:用于同步返回建议(立即计算出的结果);asyncResults:用于异步返回建议(例如来自 AJAX 请求的结果)。
source也可以是Bloodhound 实例。此时插件通过"鸭子类型"识别:若source.__ttAdapter存在则调用其适配器(见 src/typeahead/dataset.js 与 src/bloodhound/bloodhound.js 中的__ttAdapter)。Bloodhound 的完整用法可参考 doc/bloodhound.md。
async
告知数据集是否预期有异步建议。如果未设置,插件会从source函数的形参个数推断——即若source函数声明了 3 个参数,async自动为true。源码中的推断逻辑为:
this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async;异步时序由 src/typeahead/dataset.js 的update方法管理:同步结果先渲染,若同步结果数量未达到limit且async为真,则触发asyncRequested事件继续等待异步结果,异步结果到达后再通过_append追加渲染。查询一旦变化,上一次尚未完成的更新会被cancel()取消。
name
数据集名称,会被拼接到{{classNames.dataset}}-之后,形成包含该数据集的 DOM 元素的 class 名。命名规则较严格,只能由下划线、短横线、字母(a-z)和数字组成。不传时默认为一个随机数字(源码中使用_.getIdGenerator()生成的递增计数器)。合法性校验见 src/typeahead/dataset.js 的isValidName:
function isValidName(str) { return (/^[_a-zA-Z0-9-]+$/).test(str); }limit
单数据集最多展示的建议条数,默认5。同步与异步结果都会受此上限约束:同步渲染时suggestions.slice(0, that.limit),异步追加时只取that.limit - rendered条。
display
对于给定的建议对象,决定其字符串表示。该值会在用户选中某条建议后被用作输入框的值。可以是:
- 键名字符串:如
display: 'name',等价于读取suggestion.name; - 函数:接收建议对象,返回字符串,如
display: function(s) { return s.first + ' ' + s.last; }。
默认行为是对建议对象执行字符串化(_.stringify,对象会被JSON.stringify)。该函数由 src/typeahead/dataset.js 的getDisplayFn解析,并被默认的 suggestion 模板与选中逻辑共用。
templates
用于渲染数据集各区块的模板哈希。注意:预编译模板是一个接收 JavaScript 对象作为第一个参数、返回 HTML 字符串的函数。
| 模板键 | 渲染时机 | 值类型 | 模板上下文 |
|---|---|---|---|
notFound | 给定 query 没有任何建议时 | HTML 字符串或预编译模板 | 含query |
pending | 同步建议为 0 但预期有异步建议时 | HTML 字符串或预编译模板 | 含query |
header | 数据集有建议时,渲染在顶部 | HTML 字符串或预编译模板 | 含query和suggestions |
footer | 数据集有建议时,渲染在底部 | HTML 字符串或预编译模板 | 含query和suggestions |
suggestion | 渲染单条建议 | 必须是预编译模板 | 建议对象本身作为上下文 |
notFound与pending的渲染优先级在 src/typeahead/dataset.js 的_overwrite方法中体现:有建议 → 渲染建议;无建议且async且配置了pending→ 渲染 pending;无建议且非 async 且配置了notFound→ 渲染 notFound;否则清空 DOM。
suggestion未配置时使用默认模板:把display的结果包进一个div,等价于<div>{{value}}</div>。源码中默认模板为:
function suggestionTemplate(context) { return $('<div>').text(displayFn(context)); }它使用.text()写入内容,天然规避了 XSS 风险。若你提供自定义模板,建议同样对数据做转义处理。
模板上下文中的字段与源码对应关系如下(见 src/typeahead/dataset.js 的_renderNotFound、_renderPending、_getHeader、_getFooter):notFound/pending上下文为{ query, dataset };header/footer上下文为{ query, suggestions, dataset };suggestion上下文为建议对象本身(并额外注入_query字段)。
自定义事件(Custom Events)
typeahead 在整个生命周期中会在输入框元素上触发以下事件,均以typeahead:为前缀。事件通过 src/typeahead/event_bus.js 的EventBus统一派发,最终落到$.Event('typeahead:xxx')上。
| 事件 | 触发时机 | 事件处理器参数 |
|---|---|---|
typeahead:active | typeahead 进入 active 状态 | — |
typeahead:idle | typeahead 进入 idle 状态 | — |
typeahead:open | 结果容器被打开 | — |
typeahead:close | 结果容器被关闭 | — |
typeahead:change | 原生change事件的规范化版本:输入框失焦且值自获得焦点以来发生过变化 | — |
typeahead:render | 某个数据集渲染了建议 | jQuery 事件对象、渲染的建议数组、是否异步获取的标记、数据集名称 |
typeahead:select | 选中了一条建议 | jQuery 事件对象、被选中的建议对象 |
typeahead:autocomplete | 发生自动补全 | jQuery 事件对象、用于补全的建议对象 |
typeahead:cursorchange | 结果容器光标移动 | jQuery 事件对象、移到的建议对象 |
typeahead:asyncrequest | 异步建议请求发出 | jQuery 事件对象、当前 query、所属数据集名称 |
typeahead:asynccancel | 异步请求被取消 | jQuery 事件对象、当前 query、所属数据集名称 |
typeahead:asyncreceive | 异步请求完成 | jQuery 事件对象、当前 query、所属数据集名称 |
注意:并非每个事件都提供相同的参数,具体参数列表以表格中各事件为准。
事件参数与源码的对应关系:typeahead:render的 4 个参数来自 src/typeahead/typeahead.js 的_onDatasetRendered(this.eventBus.trigger('render', suggestions, async, dataset));asyncrequest/asynccancel/asyncreceive的参数分别来自_onAsyncRequested、_onAsyncCanceled、_onAsyncReceived。
示例用法:
$('.typeahead').bind('typeahead:select', function(ev, suggestion) { console.log('Selection: ' + suggestion); });兼容性补充:EventBus内部维护了旧版事件名映射(render → rendered、cursorchange → cursorchanged、select → selected、autocomplete → autocompleted),触发新事件时会同时触发旧名事件,这属于源码中的"已弃用、将在 v1 移除"的过渡行为,新代码请使用本文表格中的新事件名。
所有事件都是可"预先阻止"的——EventBus#before(type)会先触发typeahead:before<type>事件,若该事件被preventDefault(),则对应的默认行为(打开、关闭、激活、选中、补全、光标移动等)将被取消。这为拦截式交互提供了钩子。
类名(Class Names)与样式覆盖
插件默认使用tt-前缀的 class 名,完整清单如下:
| 配置键 | 作用元素 | 默认值 |
|---|---|---|
input | 被初始化为 typeahead 的输入框 | tt-input |
hint | hint 输入框 | tt-hint |
menu | 菜单元素 | tt-menu |
dataset | 数据集元素 | tt-dataset |
suggestion | 建议元素 | tt-suggestion |
selectable | 可选中项(见下) | tt-selectable |
empty | 菜单无内容时附加在菜单上 | tt-empty |
open | 菜单打开时附加在菜单上 | tt-open |
cursor | 光标移动到某条建议时附加到该建议 | tt-cursor |
highlight | 包裹高亮文本的元素 | tt-highlight |
wrapper | 输入框包装容器 | twitter-typeahead |
这些默认值定义在 src/typeahead/www.js 的defaultClassNames中。注意文档提到默认菜单元素上的tt-dataset用于数据集节点,同时每个数据集节点还会追加tt-dataset-<name>;每条建议节点则会同时带tt-suggestion与tt-selectable两个 class(见 src/typeahead/dataset.js 的_getSuggestionsFragment)。
要覆盖这些默认 class,使用classNames选项:
$('.typeahead').typeahead({ classNames: { input: 'Typeahead-input', hint: 'Typeahead-hint', selectable: 'Typeahead-selectable' } });classNames会被_.mixin({}, defaultClassNames, o)合并,即只覆盖你指定的键,其余保持默认(见 src/typeahead/www.js 的build函数)。类名一旦变更,相应的选择器、内联 HTML 与 CSS 都会同步基于新类名生成。
值得一提的还有内置的默认布局样式(同样在 src/typeahead/www.js 的buildCss中):wrapper 采用position: relative; display: inline-block,menu 采用绝对定位并默认display: none,hint 绝对定位且borderColor: transparent。这些样式在默认场景下开箱即用,开发者可在此基础上再叠加自定义样式。
键盘与交互行为补充
虽然文档主体以 API 为主,但理解键盘交互有助于调试自定义事件。核心 Typeahead 在 src/typeahead/typeahead.js 中组合了输入事件处理器:
- ↑ / ↓:移动菜单光标(
moveCursor(-1)/moveCursor(+1)),光标移动会同步更新输入框显示值,并触发typeahead:cursorchange; - Enter:选中当前光标所在的建议(
select),选中成功后阻止默认行为并关闭菜单; - Tab:有光标选中项时执行选中;否则对第一条建议执行自动补全(
autocomplete),即把建议文本填进输入框但保持焦点; - Esc:关闭菜单并重置输入值;
- → / ←:在 LTR / RTL 方向下,当光标位于输入末尾时对第一条建议执行自动补全;
- 点击:菜单中的建议项通过事件委托触发
selectableClicked,进而完成选中。
方向键与 Tab 的行为在 src/typeahead/input.js 的specialKeyCodeMap与_shouldTrigger中做了预处理(带修饰键时不触发 Tab 补全、阻止 ↑/↓ 的默认滚动行为等)。
与 Bloodhound 的组合使用
文档特别指出source可以是 Bloodhound 实例。组合用法形如:
var engine = new Bloodhound({ datumTokenizer: Bloodhound.tokenizers.whitespace, queryTokenizer: Bloodhound.tokenizers.whitespace, remote: { url: '/search?q=%QUERY' } }); $('.typeahead').typeahead(null, { name: 'search', display: 'value', source: engine });此时source传入的是 Bloodhound 实例而非函数,插件会在 src/typeahead/dataset.js 中检测到source.__ttAdapter并自动取用适配器,从而获得缓存、去重、远程请求等完整能力。Bloodhound 的远程、预取与索引细节见 doc/bloodhound.md 及 src/bloodhound/ 目录下的源码。
参考阅读
- 官方 jQuery 插件文档:doc/jquery_typeahead.md
- 插件入口与 DOM 组装:src/typeahead/plugin.js
- 核心交互与事件派发:src/typeahead/typeahead.js
- 数据集渲染与模板:src/typeahead/dataset.js
- 菜单管理与默认菜单:src/typeahead/menu.js、src/typeahead/default_menu.js
- 类名、选择器与默认 CSS:src/typeahead/www.js
- 高亮实现:src/typeahead/highlight.js
- 事件总线与旧事件名映射:src/typeahead/event_bus.js
- 插件 API 测试:test/typeahead/plugin_spec.js
- Bloodhound 文档:doc/bloodhound.md
【免费下载链接】typeahead.jstypeahead.js is a fast and fully-featured autocomplete library项目地址: https://gitcode.com/gh_mirrors/ty/typeahead.js
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考