当前位置: 首页 > news >正文

DevUI组件库实战:从入门到企业级应用的深度探索,如何实现支持表格扩展和表格编辑功能

DevUI 是一套以「设计系统为灵魂、组件库为核心、工程化工具为支撑」的企业级前端解决方案,核心优势在于「企业级场景适配、全链路一致性设计、高可定制性与工程化效率协同」。

在当今快速迭代的互联网时代,企业级前端开发面临着效率、一致性、可维护性等多重挑战。作为华为内部多年业务沉淀的结晶,DevUI应运而生——这是一款基于Angular框架的开源前端解决方案,以"高效、开放、可信、乐趣"为设计价值观,致力于为企业中后台产品提供开箱即用的前端组件库。

DevUI 为 Web 应用提供了丰富的基础 UI 组件,我们还将持续探索企业级应用的最佳 UI 实践,欢迎尝试使用 DevUI。


真实效果一:

真实效果二:

真实效果三:


真实效果:

import{Component,OnInit}from'@angular/core';import{DialogService,EditableTip,FormLayout,TableWidthConfig}from'ng-devui';import{Subscription}from'rxjs';import{FormConfig}from'src/app/@shared/components/admin-form';import{ListDataService}from'./list-data.service';@Component({selector:'da-editable-list',templateUrl:'./editable-list.component.html',styleUrls:['./editable-list.component.scss'],})exportclassEditableListComponentimplementsOnInit{editableTip=EditableTip.btn;nameEditing:boolean;busy:Subscription;pager={total:0,pageIndex:1,pageSize:10,};listData=[];headerNewForm=false;formConfig:FormConfig={layout:FormLayout.Horizontal,items:[{label:'Id',prop:'id',type:'input',},{label:'Title',prop:'title',type:'input',required:true,rule:{validators:[{required:true}],},},{label:'Priority',prop:'priority',type:'select',options:['Low','Medium','High'],required:true,rule:{validators:[{required:true}],},},{label:'Iteration',prop:'iteration',type:'input',},{label:'Assignee',prop:'assignee',type:'input',required:true,rule:{validators:[{required:true}],},},{label:'Status',prop:'status',type:'select',options:['Stuck','Done','Working on it'],},{label:'Timeline',prop:'timeline',type:'datePicker',},],labelSize:''};defaultRowData={id:'',title:'',priority:'Low',iteration:'',assignee:'',status:'Stuck',timeline:newDate(),};priorities=['Low','Medium','High'];tableWidthConfig:TableWidthConfig[]=[{field:'id',width:'150px',},{field:'title',width:'200px',},{field:'priority',width:'100px',},{field:'iteration',width:'100px',},{field:'assignee',width:'100px',},{field:'status',width:'100px',},{field:'timeline',width:'100px',},{field:'operator',width:'100px',},];constructor(privatelistDataService:ListDataService,privatedialogService:DialogService){}ngOnInit(){this.getList();}onEditEnd(rowItem,field){rowItem[field]=false;}getList(){this.busy=this.listDataService.getListData(this.pager).subscribe((res)=>{constdata=JSON.parse(JSON.stringify(res.pageList));data.$expandConfig={expand:false};this.listData=data;this.pager.total=res.total;});}beforeEditStart=(rowItem,field)=>{returntrue;};beforeEditEnd=(rowItem,field)=>{console.log('beforeEditEnd');if(rowItem&&rowItem[field].length<3){returnfalse;}else{returntrue;}};newRow(){this.headerNewForm=true;}getuuid(){returnnewDate().getTime()+'CNWO';}quickRowAdded(e){constnewData={...e};this.listData.unshift(newData);this.headerNewForm=false;}quickRowCancel(){this.headerNewForm=false;}subRowAdded(index,item){this.listData[index].$expandConfig.expand=false;constnewData={...this.defaultRowData};this.listData.splice(index+1,0,newData);}subRowCancel(index){this.listData[index].$expandConfig.expand=false;}toggleExpand(rowItem){if(rowItem.$expandConfig){rowItem.$expandConfig.expand=!rowItem.$expandConfig.expand;}}onPageChange(e){this.pager.pageIndex=e;this.getList()}onSizeChange(e){this.pager.pageSize=e;this.getList()}deleteRow(index){constresults=this.dialogService.open({id:'delete-dialog',width:'346px',maxHeight:'600px',title:'Delete',showAnimate:false,content:'Are you sure you want to delete it?',backdropCloseable:true,onClose:()=>{},buttons:[{cssClass:'primary',text:'Ok',disabled:false,handler:()=>{this.listData.splice(index,1);results.modalInstance.hide();},},{id:'btn-cancel',cssClass:'common',text:'Cancel',handler:()=>{results.modalInstance.hide();},},],});}}

这段代码是一个基于 Angular 和 DevUI 组件库实现的可编辑列表组件,主要用于展示和管理任务列表数据。以下是对代码的详细分析:

1. 组件基本信息

@Component({selector:'da-editable-list',templateUrl:'./editable-list.component.html',styleUrls:['./editable-list.component.scss'],})exportclassEditableListComponentimplementsOnInit
  • 选择器‌: 可在模板中使用
  • 模板/样式‌: 分别指向 HTML 和 SCSS 文件
  • 实现接口‌: OnInit 表示组件初始化时执行特定逻辑

2. 核心属性说明

表格配置

  • editableTip: 设置编辑提示方式为按钮触发
  • pager: 分页配置对象,包含总记录数、当前页码、每页条数
  • tableWidthConfig: 表格列宽配置数组,定义每列字段和宽度

数据模型

  • listData: 存储列表数据的数组
  • defaultRowData: 新增行的默认数据结构
  • formConfig: 表单配置对象,定义新增/编辑表单的字段、类型、验证规则等

3. 关键方法解析

生命周期钩子

ngOnInit(){this.getList();// 组件初始化时获取列表数据}

数据获取

getList(){// 调用服务获取分页数据并更新本地状态this.busy=this.listDataService.getListData(this.pager).subscribe(...)}

编辑控制

  • beforeEditStart: 编辑开始前的回调函数(始终返回 true)
  • beforeEditEnd: 编辑结束前的验证回调(字段长度需 >=3)
  • onEditEnd: 编辑完成后重置编辑状态

行操作

  • newRow(): 显示新增表单头部
  • quickRowAdded(): 快速添加新行到列表顶部
  • subRowAdded(): 在指定位置插入新行
  • toggleExpand(): 切换行展开/收起状态

分页处理

  • onPageChange(): 页码变更时重新加载数据
  • onSizeChange(): 每页条数变更时重新加载数据

删除确认

deleteRow(index){// 打开确认对话框,用户确认后从列表中移除指定行constresults=this.dialogService.open({...})}

4. 表单配置详情

formConfig 定义了包含以下字段的表单:

  • Id‌: 只读输入框
  • Title‌: 必填输入框
  • Priority‌: 必填下拉选择(低/中/高)
  • Iteration‌: 可选输入框
  • Assignee‌: 必填输入框
  • Status‌: 下拉选择(卡住/完成/进行中)
  • Timeline‌: 日期选择器

总结

这是一个功能完整的可编辑数据列表组件,具备以下特性:

  • 数据展示‌: 支持分页的任务列表展示
  • 行内编辑‌: 可直接在表格中编辑行数据
  • 新增功能‌: 支持头部快速新增和插入新行
  • 删除确认‌: 删除操作需二次确认
  • 表单验证‌: 编辑时进行数据合法性校验
  • 响应式设计‌: 通过 DevUI 表格组件实现列宽控制
<divclass="da-list-wrap"><da-layout-row[daGutter]="[24, 24]"><da-col-item[daSpan]="24"[daXs]="24"><divclass="da-list-container"dLoading[loading]="busy"><divclass="da-list-content"><d-data-table #dataTable[dataSource]="listData"[scrollable]="true"[tableWidthConfig]="tableWidthConfig"><thead dTableHead><tr dTableRow><th dHeadCell>Id</th><th dHeadCell>Title</th><th dHeadCell>Priority</th><th dHeadCell>Iteration</th><th dHeadCell>Assignee</th><th dHeadCell>Status</th><th dHeadCell>Timeline</th><th dHeadCell>Actions</th></tr></thead><tbody dTableBody><ng-templatelet-rowItem="rowItem"let-rowIndex="rowIndex"><tr dTableRow*ngIf="rowIndex === 0"><td dTableCell[attr.colspan]="tableWidthConfig.length"><div*ngIf="!headerNewForm"(click)="newRow()"class="cursor-pointer"><spanclass="tips-icon icon-add"></span><span style="margin-left: 10px">Createnewdata</span></div><div*ngIf="headerNewForm"class="edit-padding-fix"><da-admin-form[formConfig]="formConfig"[formData]="defaultRowData"class="editable-row"(submitted)="quickRowAdded($event)"(canceled)="quickRowCancel()"></da-admin-form></div></td></tr><tr dTableRow><td dTableCell[editable]="true"[editableTip]="editableTip"[(editing)]="rowItem['idEdit']"[rowItem]="rowItem"[field]="'id'"[beforeEditStart]="beforeEditStart"[beforeEditEnd]="beforeEditEnd"><span*ngIf="!rowItem['idEdit']">{{rowItem?.id}}</span><div*ngIf="rowItem['idEdit']"class="edit-padding-fix"><inputclass="devui-form-control"name="id"[(ngModel)]="rowItem.id"[attr.maxlength]="100"[attr.minlength]="3"/></div></td><td dTableCell[editable]="true"[editableTip]="editableTip"[(editing)]="rowItem['titleEdit']"[rowItem]="rowItem"[field]="'title'"[beforeEditStart]="beforeEditStart"[beforeEditEnd]="beforeEditEnd"><span*ngIf="!rowItem['titleEdit']"><d-tag[tag]="'Epic'"[labelStyle]="'epic'"></d-tag>{{rowItem?.title}}</span><div*ngIf="rowItem['titleEdit']"class="edit-padding-fix"><inputclass="devui-form-control"name="title"[(ngModel)]="rowItem.title"[attr.maxlength]="100"[attr.minlength]="3"/></div></td><td dTableCell[editable]="true"[editableTip]="editableTip"[(editing)]="rowItem['priorityEdit']"[rowItem]="rowItem"[field]="'priority'"[beforeEditStart]="beforeEditStart"[beforeEditEnd]="beforeEditEnd"><span*ngIf="!rowItem['priorityEdit']"><d-tag[tag]="rowItem?.priority"[labelStyle]="rowItem?.priority"></d-tag></span><div*ngIf="rowItem['priorityEdit']"class="edit-padding-fix"><d-select name="priority"[(ngModel)]="rowItem.priority"[options]="priorities"></d-select></div></td><td dTableCell[editable]="true"[editableTip]="editableTip"[(editing)]="rowItem['iterationEdit']"[rowItem]="rowItem"[field]="'iteration'"[beforeEditStart]="beforeEditStart"[beforeEditEnd]="beforeEditEnd"><span*ngIf="!rowItem['iterationEdit']">{{rowItem?.iteration}}</span><div*ngIf="rowItem['iterationEdit']"class="edit-padding-fix"><input dTextInput size="sm"[(ngModel)]="rowItem.iteration"/></div></td><td dTableCell[editable]="true"[editableTip]="editableTip"[(editing)]="rowItem['assigneeEdit']"[rowItem]="rowItem"[field]="'assignee'"[beforeEditStart]="beforeEditStart"[beforeEditEnd]="beforeEditEnd"><span*ngIf="!rowItem['assigneeEdit']"><d-avatar[name]="rowItem.assignee"[width]="24"[height]="24"></d-avatar><span style="margin-left: 6px">{{rowItem.assignee}}</span></span><div*ngIf="rowItem['assigneeEdit']"class="edit-padding-fix"><input dTextInput size="sm"[(ngModel)]="rowItem.assignee"/></div></td><td dTableCell[editable]="true"[editableTip]="editableTip"[(editing)]="rowItem['statusEdit']"[rowItem]="rowItem"[field]="'status'"[beforeEditStart]="beforeEditStart"[beforeEditEnd]="beforeEditEnd"><span*ngIf="!rowItem['statusEdit']"><span[ngClass]="rowItem?.status.split(' ')[0]">{{rowItem?.status||"--"}}</span></span><div*ngIf="rowItem['statusEdit']"class="edit-padding-fix"><d-select name="status"[(ngModel)]="rowItem.status"[options]="['Stuck', 'Done', 'Working on it']"></d-select></div></td><td dTableCell[editable]="true"[(editing)]="rowItem['dateEdit']"><span*ngIf="!rowItem['dateEdit']">{{rowItem?.timeline|i18nDate:"short":false}}</span><form*ngIf="rowItem['dateEdit']"class="form-inline edit-padding-fix"><divclass="devui-form-group"><divclass="devui-input-group devui-dropdown-origin"><inputclass="devui-form-control search"name="date"[(ngModel)]="rowItem.timeline"dDatepicker appendToBody #datePicker="datepicker"[autoOpen]="true"(ngModelChange)="onEditEnd(rowItem, 'dateEdit')"/><divclass="devui-input-group-addon"(click)="datePicker.toggle()"><iclass="icon icon-calendar"></i></div></div></div></form></td><td><d-button icon="icon-delete"bsStyle="text-dark"title="delete"(click)="deleteRow(rowIndex)"></d-button></td></tr></ng-template></tbody></d-data-table></div><divclass="da-list-footer"><d-pagination[size]="'sm'"[total]="pager.total"[(pageSize)]="pager.pageSize"[(pageIndex)]="pager.pageIndex"[canViewTotal]="true"[canChangePageSize]="true"[canJumpPage]="true"[maxItems]="5"(pageIndexChange)="onPageChange($event)"(pageSizeChange)="onSizeChange($event)"></d-pagination></div></div></da-col-item></da-layout-row></div>

这段代码是 Angular 模板的一部分,实现了一个可编辑的数据表格功能。以下是对代码的详细分析:

  • 使用 DevUI 布局组件创建响应式网格布局
  • dLoading 指令在数据加载时显示加载状态
  • 数据表格组件
<d-data-table #dataTable[dataSource]="listData"[scrollable]="true"[tableWidthConfig]="tableWidthConfig">
  • #dataTable: 模板引用变量,可在组件中访问表格实例
  • dataSource: 绑定表格数据源
  • scrollable: 启用滚动功能
  • tableWidthConfig: 配置各列宽度

表头定义

<thead dTableHead><tr dTableRow><th dHeadCell>Id</th><th dHeadCell>Title</th><th dHeadCell>Priority</th><th dHeadCell>Iteration</th><th dHeadCell>Assignee</th><th dHeadCell>Status</th><th dHeadCell>Timeline</th><th dHeadCell>Actions</th></tr></thead>

定义了8列表头:ID、标题、优先级、迭代、负责人、状态、时间线、操作
表格主体内容

<tbody dTableBody> <ng-template let-rowItem="rowItem" let-rowIndex="rowIndex">

使用 Angular 模板语法遍历数据行

  • rowItem: 当前行数据对象
  • rowIndex: 当前行索引

新增行功能

<tr dTableRow *ngIf="rowIndex === 0"> <td dTableCell [attr.colspan]="tableWidthConfig.length"> <div *ngIf="!headerNewForm" (click)="newRow()" class="cursor-pointer"> <span class="tips-icon icon-add"></span> <span style="margin-left: 10px">Create new data</span> </div> <div *ngIf="headerNewForm" class="edit-padding-fix"> <da-admin-form [formConfig]="formConfig" [formData]="defaultRowData" class="editable-row" (submitted)="quickRowAdded($event)" (canceled)="quickRowCancel()" ></da-admin-form> </div> </td> </tr>

在第一行显示新增数据入口

  • 点击 “Create new data” 触发 newRow() 方法
  • 显示/隐藏新增表单组件
  • 可编辑单元格示例(ID列)
<td dTableCell [editable]="true" [editableTip]="editableTip" [(editing)]="rowItem['idEdit']" [rowItem]="rowItem" [field]="'id'" [beforeEditStart]="beforeEditStart" [beforeEditEnd]="beforeEditEnd" > <span *ngIf="!rowItem['idEdit']">{{ rowItem?.id }}</span> <div *ngIf="rowItem['idEdit']" class="edit-padding-fix"> <input class="devui-form-control" name="id" [(ngModel)]="rowItem.id" [attr.maxlength]="100" [attr.minlength]="3" /> </div> </td>

关键属性说明:

属性作用
editable启用单元格编辑功能
editableTip设置编辑提示方式
editing双向绑定编辑状态
rowItem传递行数据对象
field指定编辑字段名
beforeEditStart/End编辑前后回调函数

这个表格实现了完整的 CRUD 操作,支持行内编辑、新增数据、数据验证等功能。

DevUI是华为开源的企业级前端解决方案,基于Angular框架,提供丰富的基础UI组件和工程化工具。其核心优势包括企业级场景适配、全链路一致性设计、高可定制性和工程化效率协同。该方案源自华为内部业务沉淀,以"高效、开放、可信、乐趣"为设计价值观,特别适合中后台产品开发。示例代码展示了DevUI的可编辑列表组件实现,包含表单配置、数据绑定等企业级功能。通过组件库和工具链的结合,DevUI有效解决了企业前端开发中的效率、一致性和维护性等痛点问题。


MateChat:https://gitcode.com/DevCloudFE/MateChat
MateChat官网:https://matechat.gitcode.com
DevUI官网:https://devui.design/home

http://www.jsqmd.com/news/75460/

相关文章:

  • 云顶之弈自动挂机终极指南:快速提升经验等级的秘密武器
  • Wan2.2-T2V-A14B能否准确表达‘紧张’‘欢快’等情绪氛围?
  • 终极Billion Mail离线部署指南:无互联网环境下的完整安装方案
  • 如何用容器化技术彻底解决开发环境配置难题?
  • 玩转B站视频下载:从入门到精通的完整攻略
  • Fluent Terminal:Windows命令行体验的终极解决方案
  • APK Icon Editor:快速掌握Android应用定制终极指南
  • Cursor AI编程助手试用期突破终极解决方案
  • 5步精通Wan2.2:零基础玩转AI视频创作
  • Android脱壳终极指南:BlackDex零门槛实战手册
  • Wan2.2-T2V-A14B在虚拟直播中的实时驱动可能性探究
  • Wan2.2-T2V-A14B模型在海洋馆生物介绍视频中的生态还原
  • wxhelper微信Hook终极指南:从零开始掌握PC微信自动化开发
  • 阿勒泰禾木希尔顿酒店于“中国雪都“开业
  • Calendar.js:前端开发者的终极JavaScript日历解决方案
  • RookieAI_yolov8:免费开源的终极AI自瞄完整解决方案
  • 80亿参数挑战千亿模型:DeepSeek-R1-Distill-Llama-8B如何重塑行业AI落地格局
  • 2025年靠谱的嘉兴宣传片广告制作本地视觉机构竞争力榜 - 行业平台推荐
  • Wan2.2-T2V-A14B在干细胞分化过程可视化中的微观动态捕捉
  • 2025年质量好的嘉兴企业邮箱申请/嘉兴企业邮箱开通诚信服务评选榜 - 行业平台推荐
  • TripoSR快速上手教程:从单张图片到专业3D建模
  • 从图像到视频:企业如何选择真正具备多模态能力的生成式 AI 平台? - 品牌排行榜
  • 深蓝词库转换终极指南:从零基础到精通实战教程
  • 基于Android的家政服务系统设计与实现
  • 2025年质量好的哈尔滨情侣浪漫酒店/哈尔滨城市酒店本地精选榜 - 行业平台推荐
  • 2025年热门的哈尔滨国际酒店权威推荐榜 - 行业平台推荐
  • 实用指南:【持续更新】2025华为OD机试2025双机位A卷机考真题库清单含考点说明(Java/Python/JS/C++/Go)
  • 常用设计模式:工厂方式模式
  • 从图片到文本:多模态数据分析如何重塑企业智能化能力? - 品牌排行榜
  • 文本、图像、视频全覆盖:多模态 GenAI 云平台的核心能力解析 - 品牌排行榜