DevUI组件库实战:从入门到企业级应用的深度探索,如何实现带搜索的Table表格

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

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

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


高级列表

支持列表多选和批量删除功能,支持拖拽调整列宽,支持虚拟滚动和懒加载,支持过滤。

js 复制代码
<da-layout-row [daGutter]="[24, 24]">
  <da-col-item [daSpan]="24" [daXs]="24">
    <div class="da-advance-form" dLoading [loading]="busy">
      <div class="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-template let-rowItem="rowItem" let-rowIndex="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>
              <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">
                    <input
                      class="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">
                    <input
                      class="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"
                  >
                    <div class="devui-form-group">
                      <div class="devui-input-group devui-dropdown-origin">
                        <input
                          class="devui-form-control search"
                          name="date"
                          [(ngModel)]="rowItem.timeline"
                          dDatepicker
                          appendToBody
                          #datePicker="datepicker"
                          [autoOpen]="true"
                          (ngModelChange)="onEditEnd(rowItem, 'dateEdit')"
                        />
                        <div
                          class="devui-input-group-addon"
                          (click)="datePicker.toggle()"
                        >
                          <i class="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"启用编辑

    • *ngIf="!rowItem['fieldEdit']"控制显示静态文本
    • *ngIf="rowItem['fieldEdit']"控制显示编辑输入控件
  • 不同字段使用不同的编辑控件:
    • 文本字段:输入框
    • 优先级:下拉选择器
    • 标题:带标签样式显示

5. 关键特性‌:

  • 编辑前后的钩子函数:beforeEditStart, beforeEditEnd
  • 字段验证:maxlength, minlength属性
  • 标签组件:用于高亮显示优先级和类型
  • 响应式设计:[daXs]适配小屏幕设备

整体而言,这是一个功能完整的可编辑数据表格界面,集成了数据展示、新增、编辑、验证等多种功能。

js 复制代码
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'],
})
export class AdvanceFormComponent implements OnInit {
  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: new Date(),
  };

  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(private listDataService: ListDataService, private dialogService: 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) => {
    return true;
  };

  beforeEditEnd = (rowItem, field) => {
    console.log('beforeEditEnd');
    if (rowItem && rowItem[field].length < 3) {
      return false;
    } else {
      return true;
    }
  };

  newRow() {
    this.headerNewForm = true;
  }

  getuuid() {
    return new Date().getTime() + 'CNWO';
  }

  quickRowAdded(e) {
    const newData = { ...e };
    this.listData.unshift(newData);
    this.headerNewForm = false;
  }

  quickRowCancel() {
    this.headerNewForm = false;
  }

  subRowAdded(index, item) {
    this.listData[index].$expandConfig.expand = false;
    const newData = { ...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) {
    const results = 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() 打开模态对话框让用户确认是否执行删除。

js 复制代码
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],
})
export class AdvanceFormModule {}

这段代码是 Angular 框架中的一个 NgModule(模块)定义,名为 AdvanceFormModule。它的主要作用是组织和封装与"高级表单"相关的组件、服务和依赖项,以便在应用中复用。

具体功能解析如下:

    1. 模块声明‌:通过 @NgModule 装饰器定义了一个名为 AdvanceFormModule 的 Angular 模块
    1. 组件注册‌:将 AdvanceFormComponent 组件声明在该模块中,使其可在模块内使用
    1. 依赖导入‌:导入了多个 ng-devui UI 组件库模块,如数据表格、下拉选择、标签、分页、加载指示器和日期选择器等
    1. 共享模块‌:引入了应用级别的 SharedModule,可复用通用组件和指令
      服务提供‌:在 providers 中注册了 ListDataService 服务,用于数据获取和管理
    1. 模块导出‌:将 AdvanceFormComponent 导出,使其他模块可以使用该组件
js 复制代码
import { Injectable } from '@angular/core';
import { Observable, of as observableOf } from 'rxjs';
import { delay } from 'rxjs/operators';

export interface Item {
  id?: string;
  title?: string;
  priority?: string;
  iteration?: string;
  assignee?: string;
  status?: string;
  timeline?: string;
  $checked?: boolean;
  $expandConfig?: any;
  children?: any;
  chosen?: boolean;
  $isChildTableOpen?: boolean;
}

export interface ListPager {
  pageSize?: number;
  pageIndex?: number
}


export interface CardAction {
  icon?: string;
  num?: string;
}

export interface Card {
  name?: string;
  id?: number;
  ame?: string;
  title?: string;
  imgSrc?: string;
  subTitle?: string;
  content?: string;
  agreeNum?: number;
  starsNum?: number;
  messageNum?: number;
  actions?: CardAction[];
}

@Injectable()
export class ListDataService {
  private basicData: 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',
    },
  ];

  private cardSource: 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',
        },
      ],
    },
  ];

  private pagerList(data, pager) {
    return data.slice(
      pager.pageSize * (pager.pageIndex - 1),
      pager.pageSize * pager.pageIndex
    );
  }

  getListData(pager: ListPager): Observable<any> {
    return observableOf({
      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

相关推荐
m0_471199632 小时前
【场景】用户名+密码+验证码的登录全流程
前端
恋猫de小郭2 小时前
豆包手机为什么会被其他厂商抵制?它的工作原理是什么?
android·前端·ai编程
码上成长2 小时前
长耗时接口异步改造总结
前端·git·后端
风华同学2 小时前
【系统移植篇】系统烧写
java·开发语言·前端
by__csdn2 小时前
JavaScript性能优化实战:异步与延迟加载全方位攻略
开发语言·前端·javascript·vue.js·react.js·typescript·ecmascript
牛三金2 小时前
魔改-隐语PSI通信,支持外部通信自定义
服务器·前端·算法
杨超越luckly2 小时前
HTML应用指南:利用GET请求获取全国瑞思教育门店位置信息
前端·python·arcgis·html·门店数据
尘缘浮梦2 小时前
chrome英文翻译插件
前端·chrome
HIT_Weston2 小时前
58、【Ubuntu】【Gitlab】拉出内网 Web 服务:Gitlab 配置审视(二)
前端·ubuntu·gitlab