DevUI 是一套以「设计系统为灵魂、组件库为核心、工程化工具为支撑」的企业级前端解决方案,核心优势在于「企业级场景适配、全链路一致性设计、高可定制性与工程化效率协同」。
在当今快速迭代的互联网时代,企业级前端开发面临着效率、一致性、可维护性等多重挑战。作为华为内部多年业务沉淀的结晶,DevUI应运而生——这是一款基于Angular框架的开源前端解决方案,以"高效、开放、可信、乐趣"为设计价值观,致力于为企业中后台产品提供开箱即用的前端组件库。
DevUI 为 Web 应用提供了丰富的基础 UI 组件,我们还将持续探索企业级应用的最佳 UI 实践,欢迎尝试使用 DevUI。
高级列表
支持列表多选和批量删除功能,支持拖拽调整列宽,支持虚拟滚动和懒加载,支持过滤。
<da-layout-row[daGutter]="[24, 24]"><da-col-item[daSpan]="24"[daXs]="24"><divclass="da-advance-form"dLoading[loading]="busy"><divclass="da-advace-form-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><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></da-col-item></da-layout-row>这段代码是一个基于Angular框架的前端组件模板,主要用于展示和管理一个可编辑的数据表格。下面是对代码各部分的详细解释:
1. 布局结构:
- 使用和进行响应式布局,[daGutter]设置列间距。
- dLoading指令配合[loading]="busy"实现加载状态显示。
2. 数据表格 (d-data-table):
- dataSource绑定表格数据listData
- tableWidthConfig配置列宽
- 表头定义了8列:Id, Title, Priority, Iteration, Assignee, Status, Timeline, Actions
3. 新增行功能:
- 第一行是特殊的新建数据行
- headerNewForm控制显示"新建"按钮还是表单
- 点击"Create new data"触发newRow()方法
- 表单通过da-admin-form组件渲染,支持提交(submitted)和取消(canceled)事件
4. 单元格编辑功能:
- 每个单元格都配置了编辑能力:
- [editable]="true"启用编辑
- [(editing)]双向绑定编辑状态
- *ngIf="!rowItem[‘fieldEdit’]"控制显示静态文本
- *ngIf="rowItem[‘fieldEdit’]"控制显示编辑输入控件
- 不同字段使用不同的编辑控件:
- 文本字段:输入框
- 优先级:下拉选择器
- 标题:带标签样式显示
5. 关键特性:
- 编辑前后的钩子函数:beforeEditStart, beforeEditEnd
- 字段验证:maxlength, minlength属性
- 标签组件:用于高亮显示优先级和类型
- 响应式设计:[daXs]适配小屏幕设备
整体而言,这是一个功能完整的可编辑数据表格界面,集成了数据展示、新增、编辑、验证等多种功能。
import{Component,OnInit}from'@angular/core';import{DialogService,EditableTip,TableWidthConfig}from'ng-devui';import{Subscription}from'rxjs';import{ListDataService}from'./list-data.service';import{FormLayout}from'ng-devui';import{FormConfig}from'src/app/@shared/components/admin-form/admin-form.type';@Component({selector:'da-advance-form',templateUrl:'./advance-form.component.html',styleUrls:['./advance-form.component.scss'],})exportclassAdvanceFormComponentimplementsOnInit{editableTip=EditableTip.btn;nameEditing:boolean;busy:Subscription;pager={total:0,pageIndex:1,pageSize:10,};listData=[];headerNewForm=false;formConfig:FormConfig={layout:FormLayout.Horizontal,labelSize:'sm',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',},],};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:'Actions',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)=>{res.pageList.$expandConfig={expand:false};this.listData=res.pageList;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 框架的 TypeScript 组件,名为 AdvanceFormComponent,用于实现一个具备数据展示、编辑、新增和删除功能的高级表单页面。它结合了 ng-devui UI 库提供的组件来构建一个可交互的数据表格界面。
主要功能解析:
1. 组件初始化与数据获取
- 实现了 OnInit 接口,在组件初始化时调用 getList() 方法从服务 (ListDataService) 获取初始数据并填充到页面表格中。
- 使用 pager 对象管理分页信息(如当前页码、每页条数等)。
2. 表单配置
- 定义了一个 formConfig 对象,描述了表单字段的信息(如标签、类型、校验规则)。包括:
- 输入框(Input):如 Id、Title、Iteration、Assignee。
- 下拉选择器(Select):如 Priority、Status。
- 日期选择器(DatePicker):Timeline 字段。
- 设置默认表单数据 defaultRowData,用于新行创建时的初始值。
3. 表格列宽配置
- 使用 tableWidthConfig 数组定义每一列的宽度,确保表格布局整齐美观。
4. 编辑功能
- 利用 editableTip 配置单元格编辑方式为按钮触发。
- 提供两个钩子函数 beforeEditStart 和 beforeEditEnd 控制编辑开始和结束的行为(例如限制最小长度)。
- 单元格点击后进入编辑状态,并可通过保存或取消退出编辑模式。
5. 新增行功能
- 点击 “Create new data” 触发 newRow() 显示顶部新增表单。
- 表单提交后调用 quickRowAdded() 将新数据插入列表头部。
- 取消操作则通过 quickRowCancel() 隐藏表单。
6. 展开子行功能
- 支持点击某一行展开其子项(可能用于更详细的编辑或查看)。
- 子行新增和取消分别由 subRowAdded() 和 subRowCancel() 处理。
7. 分页与刷新
页面大小改变和翻页动作会重新调用 getList() 更新数据列表。
8. 删除确认弹窗
删除操作通过 dialogService.open() 打开模态对话框让用户确认是否执行删除。
import{NgModule}from'@angular/core';import{AdvanceFormComponent}from'./advance-form.component';import{SelectModule,DataTableModule,LoadingModule,PaginationModule,TagsModule,DatepickerModule}from'ng-devui';import{SharedModule}from'src/app/@shared/shared.module';import{ListDataService}from'./list-data.service';import{AdminFormModule}from'src/app/@shared/components/admin-form';@NgModule({declarations:[AdvanceFormComponent],imports:[SharedModule,DataTableModule,LoadingModule,SelectModule,TagsModule,PaginationModule,AdminFormModule,DatepickerModule],exports:[AdvanceFormComponent],providers:[ListDataService],})exportclassAdvanceFormModule{}这段代码是 Angular 框架中的一个 NgModule(模块)定义,名为 AdvanceFormModule。它的主要作用是组织和封装与"高级表单"相关的组件、服务和依赖项,以便在应用中复用。
具体功能解析如下:
- 模块声明:通过 @NgModule 装饰器定义了一个名为 AdvanceFormModule 的 Angular 模块
- 组件注册:将 AdvanceFormComponent 组件声明在该模块中,使其可在模块内使用
- 依赖导入:导入了多个 ng-devui UI 组件库模块,如数据表格、下拉选择、标签、分页、加载指示器和日期选择器等
- 共享模块:引入了应用级别的 SharedModule,可复用通用组件和指令
服务提供:在 providers 中注册了 ListDataService 服务,用于数据获取和管理
- 共享模块:引入了应用级别的 SharedModule,可复用通用组件和指令
- 模块导出:将 AdvanceFormComponent 导出,使其他模块可以使用该组件
import{Injectable}from'@angular/core';import{Observable,ofasobservableOf}from'rxjs';import{delay}from'rxjs/operators';exportinterfaceItem{id?:string;title?:string;priority?:string;iteration?:string;assignee?:string;status?:string;timeline?:string;$checked?:boolean;$expandConfig?:any;children?:any;chosen?:boolean;$isChildTableOpen?:boolean;}exportinterfaceListPager{pageSize?:number;pageIndex?:number}exportinterfaceCardAction{icon?:string;num?:string;}exportinterfaceCard{name?:string;id?:number;ame?:string;title?:string;imgSrc?:string;subTitle?:string;content?:string;agreeNum?:number;starsNum?:number;messageNum?:number;actions?:CardAction[];}@Injectable()exportclassListDataService{privatebasicData:Item[]=[{id:'230000200706283786',title:'Yriqtjdjd Omvqxe Xxlfgjtnj Hsyf Qecu',priority:'Medium',iteration:'iteration',assignee:'Shirley Martin',status:'Stuck',timeline:'1985-01-10',children:[{id:'230000197101025982',title:'Volbp Wdobo Ukme Szbgjmeo Kobn Aawyirm Rmbobdyn',priority:'Low',iteration:'iteration',assignee:'Daniel Martinez',status:'Done',timeline:'2008-08-02',},{id:'230000197101025982',title:'Volbp Wdobo Ukme Szbgjmeo Kobn Aawyirm Rmbobdyn',priority:'Low',iteration:'iteration',assignee:'Daniel Martinez',status:'Done',timeline:'2008-08-02',children:[{id:'22000019860224174X',title:'Ozhtyax Wfpp Essvpkjrx Havonov Cdcmgmggnj Vqwcwd Ooolirn',priority:'High',iteration:'iteration',assignee:'Margaret Clark',status:'',timeline:'2015-05-08',},{id:'140000197907226183',title:'Govfunhwa Gkvcrv Uvbq Gqyrwntx Ofnnuwrnh',priority:'Low',iteration:'iteration',assignee:'Jason Rodriguez',status:'Done',timeline:'1994-02-08',},{id:'440000201807134089',title:'Rbh Wklmth Xkeg Iuzan Isufy',priority:'Medium',iteration:'iteration',assignee:'Kenneth Robinson',status:'Done',timeline:'2017-02-04',},],},{id:'520000200110166246',title:'Rrqcneg Iknm Tbo',priority:'Medium',iteration:'iteration',assignee:'Paul Hernandez',status:'Stuck',timeline:'2017-02-01',},],},{id:'710000197203093702',title:'Hwgx Vkdg Kfap Tke Miyxg Hyelo',priority:'Low',iteration:'iteration',assignee:'Michael Walker',status:'Stuck',timeline:'2018-08-04',},{id:'230000197101025982',title:'Volbp Wdobo Ukme Szbgjmeo Kobn Aawyirm Rmbobdyn',priority:'Low',iteration:'iteration',assignee:'Daniel Martinez',status:'Done',timeline:'2008-08-02',},{id:'520000200110166246',title:'Rrqcneg Iknm Tbo',priority:'Medium',iteration:'iteration',assignee:'Paul Hernandez',status:'Stuck',timeline:'2017-02-01',},{id:'22000019860224174X',title:'Ozhtyax Wfpp Essvpkjrx Havonov Cdcmgmggnj Vqwcwd Ooolirn',priority:'High',iteration:'iteration',assignee:'Margaret Clark',status:'',timeline:'2015-05-08',},{id:'140000197907226183',title:'Govfunhwa Gkvcrv Uvbq Gqyrwntx Ofnnuwrnh',priority:'Low',iteration:'iteration',assignee:'Jason Rodriguez',status:'Done',timeline:'1994-02-08',},{id:'440000201807134089',title:'Rbh Wklmth Xkeg Iuzan Isufy',priority:'Medium',iteration:'iteration',assignee:'Kenneth Robinson',status:'Done',timeline:'2017-02-04',},{id:'430000197502028524',title:'Zcbap Qqoyxrimw Hndekkk',priority:'Medium',iteration:'iteration',assignee:'Jason Garcia',status:'Done',timeline:'2009-09-09',},{id:'360000199102159374',title:'Sarbgroo Rpru Krzhklgihv Vfgha Bunyqz',priority:'Medium',iteration:'iteration',assignee:'Michelle Lee',status:'Done',timeline:'2019-02-22',},{id:'530000200702210206',title:'Tksno Nvsche Rmysrkwsy Qxjvulnsd Rzo',priority:'Medium',iteration:'iteration',assignee:'Ruth Anderson',status:'Done',timeline:'1980-01-05',},{id:'120000201207262146',title:'Mcpnwxqws Dfqrmphi Ipl',priority:'Medium',iteration:'iteration',assignee:'Susan Garcia',status:'Done',timeline:'1972-01-14',},{id:'360000199409270026',title:'Lwomkvcng Hwwj Hhjxlz',priority:'High',iteration:'iteration',assignee:'Kevin Johnson',status:'Done',timeline:'1991-06-03',},{id:'500000201603203501',title:'Mjfflwan Oebhykk Ppjpy Itnxlw Jqtm Lcsloswa',priority:'Low',iteration:'iteration',assignee:'Jennifer Harris',status:'Stuck',timeline:'2014-08-09',},{id:'130000197712017750',title:'Sdudlc Hcrfkaz Kufynndl Oprvfsh Teipjsd',priority:'High',iteration:'iteration',assignee:'Kimberly Harris',status:'Stuck',timeline:'1990-12-12',},{id:'510000201304014163',title:'Blhh Pdisxhqkl Ixnj Erbpeel Bjuvr Cdngo',priority:'High',iteration:'iteration',assignee:'Angela Martinez',status:'',timeline:'2005-04-01',},{id:'820000199503017685',title:'Bjzruarho Yqwrkksnkb Gsjr Otwbvihju',priority:'Medium',iteration:'iteration',assignee:'Ronald Hernandez',status:'Working on it',timeline:'2016-07-01',},{id:'820000198503197802',title:'Zjc Jwtut Mftvcu Ctylolht Xcdi',priority:'Low',iteration:'iteration',assignee:'Edward Wilson',status:'Stuck',timeline:'1989-03-29',},{id:'820000201707240870',title:'Cbksh Iswxgkytcw Pmbzpv Hphtfnxw',priority:'High',iteration:'iteration',assignee:'Betty Lewis',status:'Done',timeline:'1987-09-21',},{id:'460000197810188840',title:'Vmjjt Qpqjcb Ffwmwnxdn Tften Yidwthci',priority:'Low',iteration:'iteration',assignee:'Angela Jones',status:'Done',timeline:'2003-03-20',},{id:'130000198908073513',title:'Avkacxzqab Bfxtwexs Buwwvxe',priority:'High',iteration:'iteration',assignee:'Anthony Jones',status:'Stuck',timeline:'2003-02-22',},];privatecardSource:Card[]=[{name:'Angular',title:'Angular',content:'DevUI 是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计....',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'DevUI',title:'DevUI',content:'DevUI 是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计...',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'BootStrap',title:'BootStrap',content:'DevUI 是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计....',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'React',title:'React',imgSrc:'https://codingthesmartway.com/wp-content/uploads/2019/12/logo_react.png',content:'DevUI 是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计....',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'Vue',title:'Vue',imgSrc:'https://vuejs.org/images/logo.png',content:'DevUI 是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计....',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'Webpack',title:'Webpack',imgSrc:'https://webpack.js.org/icon-square-small.85ba630cf0c5f29ae3e3.svg',content:'DevUI 是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计....',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'DevUI',title:'DevUI',content:'DevUI是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计...',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'BootStrap',title:'BootStrap',content:'DevUI 是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计....',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'React',title:'React',imgSrc:'https://codingthesmartway.com/wp-content/uploads/2019/12/logo_react.png',content:'DevUI 是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计....',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'Vue',title:'Vue',imgSrc:'https://vuejs.org/images/logo.png',content:'DevUI 是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计....',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'Webpack',title:'Webpack',imgSrc:'https://webpack.js.org/icon-square-small.85ba630cf0c5f29ae3e3.svg',content:'DevUI 是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计....',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'DevUI',title:'DevUI',content:'DevUI是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计...',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'BootStrap',title:'BootStrap',content:'DevUI 是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计....',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'React',title:'React',imgSrc:'https://codingthesmartway.com/wp-content/uploads/2019/12/logo_react.png',content:'DevUI 是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计....',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'Vue',title:'Vue',imgSrc:'https://vuejs.org/images/logo.png',content:'DevUI 是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计....',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},{name:'Webpack',title:'Webpack',imgSrc:'https://webpack.js.org/icon-square-small.85ba630cf0c5f29ae3e3.svg',content:'DevUI 是面向企业中后台产品的开源前端解决方案,其设计价值观基于"至简"、"沉浸"、"灵活"三种自然与人文相结合的理念,旨在为设计....',actions:[{icon:'icon-star-o',num:'617',},{icon:'icon-fork',num:'100',},],},];privatepagerList(data,pager){returndata.slice(pager.pageSize*(pager.pageIndex-1),pager.pageSize*pager.pageIndex);}getListData(pager:ListPager):Observable<any>{returnobservableOf({pageList:this.pagerList(this.basicData,pager),total:this.basicData.length,}).pipe(delay(1000));}}这段代码是一个 Angular 服务(Service),名为 ListDataService,主要功能是为应用程序提供数据。具体分析如下:
1. 核心作用:
- 使用 @Injectable() 装饰器标记为可注入服务
- 模拟后端数据接口,提供表格/列表数据的获取功能
2. 数据结构定义:
- Item 接口:定义了列表项的数据结构,包括 id、标题、优先级、迭代、负责人、状态、时间线等字段
- 支持树形结构数据(通过 children 字段嵌套子项)
- ListPager 接口:定义分页参数(页大小、页码)
- Card 和 CardAction 接口:定义卡片数据结构(可能是另一种视图模式)
3. 数据处理:
- basicData:预置的静态模拟数据数组
- 使用 RxJS 的 Observable 和 delay 操作符模拟异步数据获取
- 提供 getTreeTableData 方法返回分页后的数据
- 支持通过 pager 参数控制数据分页
4. 技术特点:
- 采用响应式编程(RxJS)处理异步数据流
- 数据模拟:使用 delay 模拟网络请求延迟
- 类型安全:通过 TypeScript 接口严格定义数据结构
- 可扩展性:支持树形表格和普通列表两种数据格式
这是一个典型的数据服务层实现,用于前端开发中的数据模拟和状态管理。
DevUI是华为开源的企业级前端解决方案,基于Angular框架,提供丰富的基础UI组件和高效开发工具。其核心优势包括企业级场景适配、全链路一致性设计和高可定制性。示例展示了高级列表组件功能,支持多选、批量删除、拖拽列宽、虚拟滚动等特性,并提供了可编辑单元格、快速添加行等交互功能,满足复杂业务场景需求。通过代码示例可见,DevUI组件库能够显著提升中后台系统的开发效率,同时保持UI设计的一致性。
MateChat:https://gitcode.com/DevCloudFE/MateChat
MateChat官网:https://matechat.gitcode.com
DevUI官网:https://devui.design/home