☰
Mention 组件向上展开(Placement)实战指南
2026/9/27 21:26:28 网站建设 项目流程
  • UI组件
  • 前端

【免费下载链接】ng-zorro-antd

Angular UI Component Library based on Ant Design

项目地址:https://gitcode.com/gh_mirrors/ng/ng-zorro-antd
点击查看免费下载

Mention 提及组件是 Angular 生态中实现"@ 某人"交互的核心 UI 组件。默认情况下,提及建议下拉框在输入框下方展开,但在聊天、评论等贴近页面底部或空间受限的场景中,下方展开会遮挡内容甚至溢出视口。本指南围绕nzPlacement属性展开,讲解如何将建议框切换为向上展开(top),并结合仓库源码剖析其定位原理、边界行为与键盘交互,读完即可在真实项目中灵活控制建议浮层方向。

为什么需要"向上展开"

先看官方 Demo 的原始描述(placement.md):

zh-CN:向上展开建议。 en-US:Change the suggestions placement.

"向上展开"(Placement)是一个专门针对建议浮层位置的使用建议。Mention 的定位逻辑由 mention.component.ts 的updatePositions()方法驱动:组件会读取光标坐标(getCaretCoordinates),并根据nzPlacement在top与bottom两套锚点之间切换。当输入框位于页面底部、或在弹窗/抽屉/表格行内编辑等容器中时,下方没有足够空间,向上展开是更合理的交互方案。

核心 API:nzPlacement

参数说明类型默认值
[nzPlacement]建议框位置'bottom' \| 'top''bottom'

完整 API 列表见 doc/index.zh-CN.md,其中nzPlacement的取值类型定义为MentionPlacement = 'top' | 'bottom'(mention.component.ts)。

官方 Demo:向上展开

对应源码 placement.ts:

import { Component } from '@angular/core'; import { NzInputModule } from 'ng-zorro-antd/input'; import { NzMentionModule } from 'ng-zorro-antd/mention'; @Component({ selector: 'nz-demo-mention-placement', imports: [NzInputModule, NzMentionModule], template: ` <nz-mention nzPlacement="top" [nzSuggestions]="suggestions" (nzOnSelect)="onSelect($event)"> <textarea rows="1" nzMentionTrigger nz-input></textarea> </nz-mention> ` }) export class NzDemoMentionPlacementComponent { readonly suggestions = ['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']; onSelect(suggestion: string): void { console.log(`onSelect ${suggestion}`); } }

关键写法拆解

  • nzPlacement="top":把建议浮层切换到输入框上方。
  • [nzSuggestions]="suggestions":建议数据源,包含中文、日文等多语言条目,验证了top模式对任意文本的通用性。
  • nzMentionTrigger+nz-input:Mention 的触发元素,支持textarea与input两种原生元素(对应NzMentionTriggerDirective的 selectorinput[nzMentionTrigger], textarea[nzMentionTrigger],见 mention-trigger.ts)。
  • (nzOnSelect)="onSelect($event)":选择建议后的回调。

源码级原理:两套锚点如何切换

nzPlacement并非简单的 CSS 方向切换,而是直接改变浮层的锚点连接方式。定位核心逻辑在 mention.component.ts:

private updatePositions(): void { const coordinates = getCaretCoordinates(this.triggerNativeElement, this.cursorMentionStart!); const top = coordinates.top - this.triggerNativeElement.getBoundingClientRect().height - this.triggerNativeElement.scrollTop + (this.nzPlacement === 'bottom' ? coordinates.height - 6 : -6); const left = coordinates.left - this.triggerNativeElement.scrollLeft; this.positionStrategy.withDefaultOffsetX(left).withDefaultOffsetY(top); if (this.nzPlacement === 'bottom') { this.positionStrategy.withPositions([...DEFAULT_MENTION_BOTTOM_POSITIONS]); } if (this.nzPlacement === 'top') { this.positionStrategy.withPositions([...DEFAULT_MENTION_TOP_POSITIONS]); } this.positionStrategy.apply(); }

可见:top模式下浮层整体偏移量向上抬升(coordinates.height - 6变为-6),并切换到DEFAULT_MENTION_TOP_POSITIONS锚点组。这两组锚点定义在 components/core/overlay/overlay-position.ts:

export const DEFAULT_MENTION_TOP_POSITIONS = [ new ConnectionPositionPair({ originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'bottom' }), new ConnectionPositionPair({ originX: 'start', originY: 'bottom' }, { overlayX: 'end', overlayY: 'bottom' }) ]; export const DEFAULT_MENTION_BOTTOM_POSITIONS = [ POSITION_MAP.bottomLeft, new ConnectionPositionPair({ originX: 'start', originY: 'bottom' }, { overlayX: 'end', overlayY: 'top' }) ];

对比两组配置可以发现设计意图:

  • bottom(默认):浮层左上角(overlayY: 'top')对齐输入框左下角,向左下展开,同时提供右下对齐的备选。
  • top(向上展开):浮层左下角(overlayY: 'bottom')对齐输入框左下角(originY: 'bottom'),即浮层"顶在输入框上方"向下生长,并额外提供右对齐备选。

同时 getOverlayPosition() 使用 CDK 的createFlexibleConnectedPositionStrategy,并设置withFlexibleDimensions(false)与withPush(false)——浮层尺寸不被压缩、不被强制推回视口,位置完全由nzPlacement决定,保证两种模式的定位行为可预期。

覆盖场景:输入框与滚动容器的协同

nzPlacement="top"之所以实用,是因为 Mention 浮层默认以body为滚动容器。当输入框位于页面底部或自定义滚动容器(如弹窗、抽屉)内时,向下展开的浮层很容易超出视口;切换到top后浮层在输入框上方生长,天然规避了"底部溢出"问题。

官方 FAQ(doc/index.zh-CN.md)也补充了相关注意点:如果使用了自定义滚动容器,需要在滚动容器元素上添加 CDK 的CdkScrollable指令(从@angular/cdk/scrolling导入),浮层才能跟随滚动。这与top模式配合使用,可以完整覆盖"页面底部输入 + 自定义滚动容器"的高难度布局。

交互行为在 top 模式下的表现

nzPlacement只影响浮层方向,不改变交互逻辑。向上展开时以下行为保持不变(源码见 mention.component.ts 的handleKeydown):

  • 键盘导航:UP_ARROW/DOWN_ARROW在建议项间循环移动(setPreviousItemActive/setNextItemActive),ENTER选中当前项,TAB/ESCAPE关闭浮层。
  • 光标跟随:浮层位置基于光标所在处(getCaretCoordinates)而非输入框整体,输入过程中浮层始终跟随光标。
  • 失焦关闭:点击浮层外部区域或按下touchend会关闭浮层(subscribeOverlayOutsideClick)。

测试用例也印证了top模式的完整支持,mention.spec.ts 中的NzTestPropertyMentionComponent使用nzPlacement="top"结合nzValueWith、nzPrefix、nzLoading、nzMentionSuggestion自定义模板进行集成测试,覆盖了top与复杂配置组合的场景。

综合示例:贴近页面底部的发布输入框

将top模式与常见发布场景结合,完整可运行模板如下:

import { Component } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { NzInputModule } from 'ng-zorro-antd/input'; import { NzMentionModule } from 'ng-zorro-antd/mention'; @Component({ selector: 'app-comment-box', standalone: true, imports: [FormsModule, NzInputModule, NzMentionModule], template: ` <div style="position: fixed; bottom: 0; left: 0; right: 0; padding: 12px; background: #fff;"> <nz-mention nzPlacement="top" [nzSuggestions]="suggestions" [nzPrefix]="['@', '#']" (nzOnSelect)="onSelect($event)" (nzOnSearchChange)="onSearchChange($event)" > <textarea rows="2" nz-input nzMentionTrigger [(ngModel)]="content" placeholder="输入 @ 提及成员" ></textarea> </nz-mention> </div> ` }) export class CommentBoxComponent { content = ''; suggestions = ['alice', 'bob', 'carol', '管理员', '产品组']; onSelect(item: string): void { console.log('选中:', item); } onSearchChange(e: { value: string; prefix: string }): void { console.log(`触发前缀 ${e.prefix},搜索关键词 ${e.value}`); } }

要点:

  • nzPlacement="top"确保固定在页面底部的输入框,建议浮层向上弹出,不遮挡正文内容。
  • [nzPrefix]="['@', '#']"支持多种触发字符(见 mention.component.ts 的nzPrefix: string | string[] = '@'默认值)。
  • nzOnSearchChange事件携带{ value, prefix }(MentionOnSearchTypes),可用于远程搜索;nzSuggestions与nzValueWith支持对象型建议数据与自定义显示。

小结

nzPlacement提供了'bottom'(默认)与'top'(向上展开)两种建议浮层方向,切换时底层会替换整套连接锚点(DEFAULT_MENTION_BOTTOM_POSITIONS/DEFAULT_MENTION_TOP_POSITIONS)并调整光标偏移量。向上展开模式尤其适合页面底部输入、弹窗与抽屉内编辑、自定义滚动容器等"下方空间不足"的场景,且完整保留键盘导航、光标跟随与失焦关闭等全部交互能力。相关参考:Demo 描述、Demo 源码、组件实现、组件 API 文档、锚点定义。

  • UI组件
  • 前端

【免费下载链接】ng-zorro-antd

Angular UI Component Library based on Ant Design

项目地址:https://gitcode.com/gh_mirrors/ng/ng-zorro-antd
点击查看免费下载
上一篇:如何为Sublime Text创建自定义语法高亮:从入门到精通
下一篇:nopecha-extension自动化构建流程:从代码到发布的CI/CD管道

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询