
UI组件前端【免费下载链接】ng-zorro-antdAngular UI Component Library based on Ant Design项目地址https://gitcode.com/gh_mirrors/ng/ng-zorro-antd点击查看免费下载导读本文围绕 ng-zorro-antd 组件库中 Tag 标签的「动态添加和删除」Add Remove Dynamically场景展开以官方 demo components/tag/demo/control.ts 为完整示例讲解如何用数组驱动渲染一组标签并通过nzModecloseable、nzOnClose事件与内联输入框实现动态删除、动态新增。读完本文你将掌握数组驱动的标签渲染范式、删除与新增的完整事件链路、去重与空值校验、长标签截断展示以及nz-tag组件的底层关闭实现原理与测试验证方式。一、场景概述为什么需要动态管理标签Tag 组件在 ng-zorro-antd 中属于「数据展示」类组件见 components/tag/doc/index.zh-CN.md核心用途是标记事物的属性和维度、进行分类。但在真实业务中标签集合很少是静态写死的——用户往往需要自行追加新标签、删除不再需要的旧标签例如编辑文章的关键词列表配置告警/搜索的过滤条件管理用户的自定义分组或技能点。官方文档对这一场景的定位非常简洁明确用数组生成一组标签可以动态添加和删除见 components/tag/demo/control.md。即视图完全由组件类中的一个响应式数组驱动数组的变化会同步反映为界面上标签的增删这正是 Angular 响应式编程signal在表单类交互中的典型应用。二、核心实现数组驱动的标签增删完整代码官方提供的control示例完整实现了「初始一组标签 → 逐个删除 → 点击 New Tag 输入 → 确认后追加 → 去重校验」的全流程。核心组件 components/tag/demo/control.ts 定义如下关键逻辑已注释import { Component, ElementRef, ViewChild, signal } from angular/core; import { FormsModule } from angular/forms; import { NzNoAnimationDirective } from ng-zorro-antd/core/animation; import { NzIconModule } from ng-zorro-antd/icon; import { NzInputModule } from ng-zorro-antd/input; import { NzTagModule } from ng-zorro-antd/tag; Component({ selector: nz-demo-tag-control, imports: [FormsModule, NzIconModule, NzInputModule, NzTagModule, NzNoAnimationDirective], template: for (tag of tags(); track tag) { nz-tag [nzMode]$first ? default : closeable (nzOnClose)handleClose(tag) {{ sliceTagName(tag) }} /nz-tag } if (!inputVisible()) { nz-tag classeditable-tag nzNoAnimation (click)showInput() nz-icon nzTypeplus / New Tag /nz-tag } else { input #inputElement nz-input nzSizesmall typetext [ngModel]inputValue() (ngModelChange)inputValue.set($event) stylewidth: 78px; (blur)handleInputConfirm() (keydown.enter)handleInputConfirm() / } , styles: .editable-tag { background: rgb(255, 255, 255); border-style: dashed; } }) export class NzDemoTagControlComponent { readonly tags signal([Unremovable, Tag 2, Tag 3]); readonly inputVisible signal(false); readonly inputValue signal(); ViewChild(inputElement, { static: false }) inputElement?: ElementRef; handleClose(removedTag: string): void { this.tags.update(tags tags.filter(tag tag ! removedTag)); } sliceTagName(tag: string): string { const isLongTag tag.length 20; return isLongTag ? ${tag.slice(0, 20)}... : tag; } showInput(): void { this.inputVisible.set(true); setTimeout(() { this.inputElement?.nativeElement.focus(); }, 10); } handleInputConfirm(): void { const inputValue this.inputValue(); if (inputValue this.tags().indexOf(inputValue) -1) { this.tags.update(tags [...tags, inputValue]); } this.inputValue.set(); this.inputVisible.set(false); } }这段代码包含四个值得拆解的工程要点下面逐一展开。2.1 数组渲染与首项不可删除模板通过for (tag of tags(); track tag)遍历 signal 数组tags()渲染标签。注意两个细节track tag指定跟踪键帮助 Angular 在数组变化时复用 DOM 节点避免整组重建[nzMode]$first ? default : closeable只有第一项$first为true时使用不可关闭的default模式其余标签全部启用closeable模式显示关闭图标。这一技巧常用于「至少保留一个基础标签、其余可自由删除」的交互设计——示例中第一个标签Unremovable不可删除正是靠这个条件表达式实现的。2.2 删除链路nzOnClose 事件 → 数组过滤每个可关闭标签绑定了(nzOnClose)handleClose(tag)点击关闭图标后执行handleClose(removedTag: string): void { this.tags.update(tags tags.filter(tag tag ! removedTag)); }这里使用 signal 的update方法以不可变更新的方式从数组中剔除被删除的标签随后模板中的for自动重新渲染。这一设计保证了数据流单向清晰UI 事件 → 组件状态 → 视图刷新不依赖任何 DOM 层面的手工操作。2.3 新增链路占位标签 → 内联输入框 → 确认追加新增流程由两个状态位驱动inputVisible是否显示输入框与inputValue当前输入内容未显示输入框时渲染一个虚线边框样式的可点击标签classeditable-tag样式为border-style: dashed内含nz-icon nzTypeplus加号图标文案为 New Tag。点击后调用showInput()将inputVisible置为true。显示输入框时渲染一个nz-input小尺寸文本输入框width: 78px通过[ngModel]/(ngModelChange)与inputValue双向同步。回车keydown.enter或失焦blur都会触发handleInputConfirm()这是「确认提交」的两种等价入口兼顾键盘快捷操作与鼠标点击别处的自然习惯。showInput()中通过setTimeout(..., 10)延后调用inputElement.nativeElement.focus()确保 Angular 完成视图渲染、输入框真正挂载后再聚焦实现「点击即输入」的无缝体验。handleInputConfirm()完成三项收尾工作const inputValue this.inputValue(); if (inputValue this.tags().indexOf(inputValue) -1) { this.tags.update(tags [...tags, inputValue]); } this.inputValue.set(); this.inputVisible.set(false);空值拦截inputValue为 falsy空字符串时不执行追加去重校验通过indexOf(inputValue) -1判断数组是否已存在同名标签存在则忽略避免重复标签状态复位无论是否追加成功都清空输入值并隐藏输入框回到「New Tag」占位状态便于下一次操作。2.4 长标签截断展示sliceTagName()在模板中对每个标签文本做了防御性处理当标签长度超过 20 个字符时截取前 20 个字符并追加省略号...。这保证了超长自定义标签不会撑破布局是一种低成本且实用的 UI 兜底策略。三、源码级原理nz-tag 的关闭事件到底发生了什么要真正理解动态删除需要深入nz-tag组件本体 components/tag/tag.component.ts 的实现。3.1 nzMode 与关闭图标渲染NzTagComponent的模板components/tag/tag.component.ts#L29-L34如下ng-content / if (nzMode closeable) { nz-icon nzTypeclose classant-tag-close-icon tabindex-1 (click)closeTag($event) / }可见关闭图标仅在nzMode closeable时渲染这也解释了示例模板中为何要对非首项标签显式设置nzModecloseable——默认值default模式下根本没有关闭按钮。nzMode的取值类型为default | closeable | checkable默认default见 components/tag/doc/index.zh-CN.md 的 API 表。3.2 closeTag 的内部链路与 preventDefault 拦截点击关闭图标触发closeTag(e)components/tag/tag.component.ts#L68-L73closeTag(e: MouseEvent): void { this.nzOnClose.emit(e); if (!e.defaultPrevented) { this.renderer.removeChild(this.renderer.parentNode(this.el), this.el); } }这里蕴含了一个重要机制事件先向上抛出nzOnClose再根据事件是否被阻止默认行为决定是否物理移除 DOM。也就是说如果业务代码如示例中的handleClose只负责更新自己的数据数组没有调用event.preventDefault()那么组件会额外执行renderer.removeChild把自身从 DOM 中移除如果业务方希望「阻止关闭」——比如在关闭前弹出确认、或希望完全由自己的数据层控制 DOM——只需要在nzOnClose处理器中调用e.preventDefault()组件便会尊重该决定不执行 DOM 移除。这一行为被官方测试 components/tag/tag.spec.ts 明确验证should close prevent default用例中处理器内调用e.preventDefault()后关闭图标在点击后依然存在而should closeable work用例则验证了未阻止默认行为时点击.anticon-close后nz-tag节点从 DOM 中消失且onClose恰好被调用一次。注意示例中的handleClose没有调用preventDefault所以关闭流程是「数组过滤 DOM 移除」双保险同时生效而for渲染会因数组变化重新生成视图最终界面呈现一致的删除结果。在纯 signal 数组驱动的写法下通常无需依赖组件的自动 DOM 移除逻辑但了解该机制有助于处理「带确认弹窗的删除」「禁止删除某些标签」等进阶需求。3.3 相关 API 一览结合官方文档与源码nz-tag在本场景中涉及的核心 API 汇总如下完整定义见 components/tag/doc/index.zh-CN.md参数说明类型默认值[nzMode]设定标签工作的模式closeable \| default \| checkabledefault[nzChecked]标签选中状态可双向绑定checkable模式可用booleanfalse[nzColor]标签色string-[nzBordered]是否有边框booleantrue(nzOnClose)关闭时的回调closeable模式可用EventEmitterMouseEvent-(nzCheckedChange)选中状态变化的回调checkable模式可用EventEmitterboolean-其中nzColor的类型NzTagColor为NzPresetColor | NzStatusColor | (string {})见 components/tag/typings.ts支持预设色、状态色如success、processing与任意自定义字符串。若想为本示例的标签增加色彩区分直接绑定[nzColor]即可例如给首项固定标签使用success状态色以强化「不可删除」的视觉暗示。四、模块引入与运行前提使用本示例前需要引入以下依赖与 components/tag/demo/control.ts 的imports保持一致NzTagModule来自ng-zorro-antd/tag提供nz-tag组件模块定义为「imports exportsNzTagComponent」的轻量封装见 components/tag/tag.module.tsNzInputModuleng-zorro-antd/input提供nz-input指令NzIconModuleng-zorro-antd/icon提供nz-icon及plus、close图标FormsModuleangular/forms支撑ngModel双向绑定NzNoAnimationDirectiveng-zorro-antd/core/animation作用于editable-tag占位标签关闭其过渡动画避免点击占位标签时的动画闪烁干扰输入框切换体验。当前仓库为 standalone 组件架构示例通过Component.imports直接声明依赖若项目仍使用 NgModule 组织方式可将这些模块导入到所属模块的imports中效果一致。五、测试验证与可复用的工程结论仓库中的 components/tag/tag.spec.ts 为上述交互提供了自动化保障可提炼出三条与动态删除直接相关的测试事实图标渲染随模式变化mode为default时页面不存在.anticon-close切换为closeable后关闭图标出现默认删除行为点击关闭图标后onClose被调用 1 次且whenStable()后nz-tag节点从 DOM 中消失可拦截关闭nzOnClose中调用event.preventDefault()后标签不会被移除——这是实现「二次确认删除」「权限拦截」等业务增强的官方标准姿势。结合示例本身可以沉淀出可复用的工程模式状态全部收敛到 signal 数组增删只改数据视图交由for自动同步新增入口用「占位标签 ↔ 输入框」二态切换通过inputVisible控制配合blur/enter双触发提交提交时同时做空值过滤与去重校验保证标签集合的整洁性长文本统一走截断函数避免布局被超长标签破坏需要拦截删除时在nzOnClose中preventDefault()由业务侧完全接管删除决策。这套组合可以直接迁移到任何「可编辑标签集合」的表单场景是 ng-zorro-antd Tag 组件最核心的动态交互范式。参考资料官方示例说明components/tag/demo/control.md示例完整源码components/tag/demo/control.ts组件实现components/tag/tag.component.tsAPI 文档components/tag/doc/index.zh-CN.md类型定义components/tag/typings.ts模块封装components/tag/tag.module.ts测试用例components/tag/tag.spec.ts赞分享UI组件前端【免费下载链接】ng-zorro-antdAngular UI Component Library based on Ant Design项目地址https://gitcode.com/gh_mirrors/ng/ng-zorro-antd点击查看免费下载相关推荐Ant Design Tag 动态标签管理实战用数组驱动标签的新增、删除与编辑Ant Design Tag 动态标签管理实战用数组驱动标签的新增、删除与编辑 在 Ant Design 中 Tag 组件最常见的进阶用法是「动态标签管理」前端UI组件设计系统antd Tag 添加与删除动画实战基于 rc-tween-one 的 TweenOneGroup 标签动效方案antd Tag 添加与删除动画实战基于 rc tween one 的 TweenOneGroup 标签动效方案 在 ant design 组件库中Tag前端UI组件设计系统Worktrunk钩子审批机制全解团队共享命令安全运行的三道防线Worktrunk钩子审批机制全解团队共享命令安全运行的三道防线 Worktrunk 是一个面向 Git worktree 管理的命令行工具专为多 AI AUI组件前端上一篇gh_mirrors/ba/bases配置验证工具确保JSON语法正确的检查器下一篇MonoGame字体图集生成BMFont与自定义渲染器终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考