- UI组件
- 前端
【免费下载链接】ng-zorro-antd
Angular UI Component Library based on Ant Design
在 ng-zorro-antd 的 Select 组件中,「搜索框」Demo 演示了如何将可搜索的下拉选择器与远程数据请求相结合:用户输入关键词后,组件把输入值交给后端接口查询,再把返回结果作为选项渲染到下拉列表中。本文以 search-box 示例 为主线,结合 Select 源码 拆解nzShowSearch、nzServerSearch、nzFilterOption、nzOnSearch四个关键 API 的配合方式与底层实现原理,读完即可在真实项目中落地「输入即搜索」的远程数据选择器,并清晰理解它与本地过滤搜索的区别。
一、示例定位:搜索与远程数据结合
仓库中 search-box.md 的描述极为精炼——zh-CN 为「搜索和远程数据结合」,en-US 为「Search with remote data」。它对应的是一个**服务端搜索(Server Search)**场景:选项数据不在前端静态声明,而是由接口按关键词动态返回,适合数据量大、无法一次性下发给前端的业务(如电商商品、用户检索、城市联想等)。
完整的示例实现位于 search-box.ts,核心模板如下:
<nz-select [nzOptions]="options()" nzShowSearch nzServerSearch nzPlaceHolder="input search text" [nzShowArrow]="false" [nzFilterOption]="filterFn" (nzOnSearch)="search($event)" />对应的组件逻辑:
@Component({ selector: 'nz-demo-select-search-box', imports: [NzSelectModule], template: `<!-- 上述 nz-select 模板 -->`, styles: `nz-select { width: 200px; }` }) export class NzDemoSelectSearchBoxComponent { private readonly http = inject(HttpClient); readonly options = signal<Array<{ label: string; value: string }>>([]); readonly filterFn = (): boolean => true; search(value: string): void { this.http .jsonp<{ result: Array<[string, string]> }>(`YOUR_SUGGEST_API?q=${value}`, 'callback') .subscribe(data => { const options = data.result.map(([item]) => ({ label: item, value: item })); this.options.set(options); }); } }说明:原示例通过 Angular 的
HttpClient.jsonp()访问外部建议类接口(Angular 的 JSONP 能力按约定需要应用引入HttpClientJsonpModule支持),返回的二元组数组被映射为{ label, value }选项列表。实际项目中可将jsonp替换为常规的HttpClient.get()/post()或你自己的数据服务。
该示例有几个一眼可见的细节,都对应 Select 组件的高频配置:
| 配置 | 取值 | 作用 |
|---|---|---|
nzShowSearch | true | 开启搜索,使单选模式下也能输入关键词 |
nzServerSearch | true | 声明为服务端搜索,关闭前端本地过滤 |
[nzFilterOption] | () => true | 过滤函数恒返回true,即“不过滤任何选项” |
[nzShowArrow] | false | 隐藏下拉箭头,弱化“下拉”外观、突出“输入搜索” |
(nzOnSearch) | search($event) | 输入变化时触发远程请求 |
[nzOptions] | options() | 选项列表由远程结果动态驱动 |
二、关键 API 拆解:四个参数如何配合完成远程搜索
要理解这个 Demo,需要把 Select 组件 API 文档 中与搜索相关的四个 API 串起来。它们在 select.component.ts 中均有对应声明:
nzShowSearch:类型boolean,默认false,booleanAttribute转换(select.component.ts)。使单选模式可搜索,没有它,输入框不会出现在单选 Select 中。注意组件宿主的ant-select-show-search样式类在nzShowSearch || nzMode !== 'default'时才会挂上(select.component.ts),即多选模式下默认就带搜索输入框。nzServerSearch:类型boolean,默认false(select.component.ts)。是否使用服务端搜索——为true时组件不再在前端对nz-option/nzOptions做过滤,把“哪些选项匹配”完全交给远程数据。nzFilterOption:类型(input?: string, option?: NzSelectItemInterface) => boolean(select.types.ts)。本地过滤模式下判断某个选项是否命中关键词;示例中恒返回true,等价于“保留所有选项,匹配逻辑由远程决定”。(nzOnSearch):EventEmitter<string>(select.component.ts)。文本框值变化时的回调,携带最新输入值,是远程请求的触发点。
此外还有两个常被一起使用的配套项:
nzOptions:Array<{ label; value; disabled?; hide?; groupLabel?; ... }>(select.types.ts),可用它取代子组件nz-option声明选项,非常适合以数据驱动、由远程结果批量替换的场景——这正是搜索框 Demo 采用的方式。nzLoading:类型boolean,默认false,用于在请求进行中展示加载态(配合nzShowArrow时的加载图标/搜索图标切换,见 select-arrow 使用处)。
三、源码级原理:远程搜索如何“接管”选项过滤
远程搜索的核心在于:组件内部把“前端过滤”这条链路让位给“远程数据”。以下三段源码可以完整还原这一机制。
1. 默认本地过滤函数
当开发者不传nzFilterOption时,组件使用内置的默认实现defaultFilterOption:
const defaultFilterOption: NzFilterOptionType = (searchValue: string, item: NzSelectItemInterface): boolean => { if (item && item.nzLabel) { return item.nzLabel.toString().toLowerCase().indexOf(searchValue.toLowerCase()) > -1; } return false; };(select.component.ts)
可见默认规则是对选项标签做忽略大小写的子串匹配(indexOf),这也是nzFilterOption参数的默认值(select.component.ts)。
2. 选项容器的过滤分支
真正决定“本地过滤是否生效”的是updateListOfContainerItem():
let listOfContainerItem = this.listOfTagAndTemplateItem .filter(item => !item.nzHide) .filter(item => { if (!this.nzServerSearch && this.searchValue) { return this.nzFilterOption(this.searchValue, item); } else { return true; } });(select.component.ts)
关键分支一目了然:只有**「未开启nzServerSearch」且「有输入值」**时,才会调用nzFilterOption过滤;一旦nzServerSearch为true,所有选项原样保留(return true)。这就是为什么远程搜索 Demo 里即使nzFilterOption恒返回true也不会造成“选项被全部保留而混乱”——因为远端接口返回的本来就只是与关键词匹配的结果。
3. 输入事件到远程回调的链路
输入框的每一次变化会沿以下调用链传递:
onInputValueChange(value: string): void { this.searchValue = value; this.updateListOfContainerItem(); this.nzOnSearch.emit(value); // 触发 (nzOnSearch) this.updateCdkConnectedOverlayPositions(); }(select.component.ts)
即:输入变化 → 更新内部searchValue→ 重建选项容器(这里走的是“远程模式不过滤”的分支)→向外发射nzOnSearch→ 刷新浮层位置。开发者监听nzOnSearch拿到的就是实时的输入文本,可据此发起远程请求。
4. 输入框本身的实现细节
搜索输入框由独立的 select-search.component.ts 渲染,其中值得关注两点:
- 输入框设置了
autocomplete="off"并绑定ngModel(standalone),(ngModelChange)触发onValueChange向上抛值(select-search.component.ts); - 组件显式处理了
compositionstart/compositionend(select-search.component.ts),并在providers中配置COMPOSITION_BUFFER_MODE = false——这是为了正确区分中文等输入法的组词过程与最终确认,避免拼音拼写过程中就触发远程搜索,是中文场景下的关键细节。
四、从示例到实战:接入你自己的远程数据源
基于上面原理,落地一个远程搜索选择器的通用模式如下:
@Component({ selector: 'app-user-select', imports: [NzSelectModule], template: ` <nz-select [nzOptions]="userOptions()" nzShowSearch nzServerSearch [nzLoading]="loading()" nzPlaceHolder="请输入用户名搜索" [nzFilterOption]="alwaysTrue" (nzOnSearch)="onSearch($event)" /> ` }) export class AppUserSelect { private readonly http = inject(HttpClient); readonly userOptions = signal<Array<{ label: string; value: string }>>([]); readonly loading = signal(false); readonly alwaysTrue = (): boolean => true; onSearch(keyword: string): void { if (!keyword.trim()) { this.userOptions.set([]); return; } this.loading.set(true); this.http .get<Array<{ id: string; name: string }>>(`/api/users?keyword=${encodeURIComponent(keyword)}`) .subscribe({ next: users => this.userOptions.set(users.map(u => ({ label: u.name, value: u.id }))), complete: () => this.loading.set(false) }); } }结合 搜索框示例 与组件源码,以下是值得注意的工程细节:
- 结果结构统一映射:无论接口返回什么结构,最终都要映射为
{ label, value }(可扩展disabled、groupLabel等字段)赋值给nzOptions,组件便自动完成选项渲染与选中值绑定; - 空关键词处理:从
onInputValueChange的实现看,空输入同样会触发nzOnSearch,实战中应在回调内对空串提前短路(如上例),避免无效请求; - 加载态与错误处理:请求期间用
nzLoading呈现加载状态;远程请求失败时建议回填空选项并给出提示(nzNotFoundContent可自定义空数据展示内容); - 请求频率:源码每次输入都会同步触发
nzOnSearch,高频输入会造成请求风暴,建议按需在回调外层做防抖/竞态处理(如switchMap或取消旧请求),这属于应用层职责; - 中文输入:组件已处理好输入法组词阶段不触发搜索,因此
composition相关逻辑无需再在业务侧重复处理。
五、本地搜索 vs 远程搜索:何时用哪一种
仓库中另有一个 search 示例(实现见 search.ts),与搜索框示例形成对照:它只设置nzShowSearch与nzAllowClear,选项在组件内静态声明,完全走本地过滤。
<nz-select [nzOptions]="options" nzShowSearch nzAllowClear nzPlaceHolder="Select a person" />两者的本质区别就一句话:本地搜索的过滤发生在组件内部(默认子串匹配,可用nzFilterOption自定义),远程搜索的过滤发生在服务端(前端不做过滤,选项由接口返回)。
| 维度 | 本地搜索(search 示例) | 远程搜索(搜索框示例) |
|---|---|---|
nzServerSearch | false | true |
| 选项来源 | 静态声明或一次性加载 | 每次输入动态请求 |
| 过滤位置 | 组件内部(nzFilterOption默认子串匹配) | 服务端,前端恒保留选项 |
| 适用场景 | 选项量小、可全量下发 | 数据量大、需按关键词检索 |
nzOnSearch | 非必需 | 必需(远程请求的触发点) |
判断依据:若你的选项总量可控、能一次加载,用本地搜索即可,省去网络延迟与接口开发;若数据量大、无法全量下发,或需要复杂的服务端检索逻辑,则用远程搜索。若你还需要下拉滚动到底部自动加载更多远程数据,可进一步参考同目录下的 scroll-load 示例(配合nzScrollToBottom输出事件,源码见 select.component.ts)。
六、小结与延伸阅读
「搜索框」Demo 虽短,却完整展示了 ng-zorro-antd Select 服务端搜索的标准用法:nzShowSearch开启输入、nzServerSearch关闭本地过滤、nzFilterOption让位、nzOnSearch承接远程请求、nzOptions动态接管选项。其底层机制——本地过滤分支与nzOnSearch发射链路——在 select.component.ts 与 select.component.ts 中清晰可查。
如果想继续深入,推荐按以下路径阅读仓库相关文件:
- 示例入口:components/select/demo/search-box.md、components/select/demo/search-box.ts
- 本地搜索对照:components/select/demo/search.md、components/select/demo/search.ts
- Select 完整 API:components/select/doc/index.zh-CN.md
- 组件核心实现:components/select/select.component.ts
- 搜索输入框实现:components/select/select-search.component.ts
- 类型定义:components/select/select.types.ts
- UI组件
- 前端
【免费下载链接】ng-zorro-antd
Angular UI Component Library based on Ant Design
相关推荐
Ant Design Select 搜索框:搜索与远程数据结合的完整实践指南
Ant Design Select 搜索框:搜索与远程数据结合的完整实践指南 导读 本篇文章围绕 Ant Design 中 Select 组件的「搜索 + 远程
前端UI组件设计系统ng-zorro-antd Mention 异步加载实战:用 `(nzOnSearchChange)` 实现远程搜索建议
ng zorro antd Mention 异步加载实战:用 nzOnSearchChange 实现远程搜索建议 当匹配内容列表需要异步返回时(例如从远程接口拉
UI组件前端终极8051单片机JSON解析优化指南:cJSON极致内存压缩方案
终极8051单片机JSON解析优化指南:cJSON极致内存压缩方案 面对8051单片机仅128字节RAM和4KB ROM的极端资源限制,你是否曾为JSON数据交
序列化
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考