AngularJS 中实现列表拖拽功能

34 阅读3分钟

最近在做一款 AngularJS 框架写的 App. AngularJS 框架的组件库相比 React 较少,因此对有些复杂功能的实现稍显吃力。在本文中,实现Angular中的拖拽功能,可以使用@angular/cdk/drag-drop模块。以下是一些基本的步骤和示例代码:

1. 实现基础的拖拽功能

  1. 导入DragDropModule: 首先,需要在你的Angular模块中导入DragDropModule。这样你就可以在组件中使用cdkDrag指令了。

    import { DragDropModule } from '@angular/cdk/drag-drop';
    @NgModule({
      imports: [
        DragDropModule
      ],
      // ... other metadata properties
    })
    export class AppModule { }
    
  2. 使用cdkDrag指令: 在HTML模板中,使用cdkDrag指令来指定哪些元素可以被拖拽。

    <div cdkDrag class="drag-box">Drag me</div>
    
  3. 创建拖拽列表: 如果你想拖拽列表中的项目,可以将cdkDrag指令用在列表的每个项目上,并使用cdkDropList来包裹列表。

    <ul cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
      <li *ngFor="let item of items" cdkDrag>{{item}}</li>
    </ul>
    
  4. 处理拖拽事件: 在组件的 TypeScript 文件中,处理拖拽事件来更新你的数据模型。

    import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
    
    // ... in your component class ...
    drop(event: CdkDragDrop<string[]>) {
      moveItemInArray(this.items, event.previousIndex, event.currentIndex);
    }
    
  5. 连接多个拖拽列表: 你可以将多个cdkDropList连接起来,使得项目可以在它们之间转移。

    <ul cdkDropList [cdkDropListConnectedTo]="['list2']" class="example-list">
      <li *ngFor="let item of list1" cdkDrag>{{item}}</li>
    </ul>
    <ul cdkDropList #list2 class="example-list">
      <li *ngFor="let item of list2" cdkDrag>{{item}}</li>
    </ul>
    
  6. 添加动画效果: 你可以为拖拽操作添加动画效果,以增强用户体验。

    .example-box {
      transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
    }
    .cdk-drag-animating {
      transition: transform 300ms cubic-bezier(0, 0, 0.2, 1);
    }
    
  7. 自定义拖拽手柄: 你可以使用cdkDragHandle来指定哪个元素可以作为拖拽手柄。

    <div cdkDrag>
      <span cdkDragHandle class="drag-handle">Drag handle</span>
      Item content
    </div>
    

2. 拖动时动态绑定类名

在Angular CDK的拖拽模块中,你可以通过监听拖拽事件来动态添加或移除类名。这可以通过在组件的TypeScript文件中实现事件处理函数,并在模板中使用[class]="..."[ngClass]="..."来绑定类名。

以下是如何实现在拖动时添加类名的步骤:

  1. 定义类名: 在你的组件的TypeScript文件中,定义一个变量来跟踪拖拽状态,并在适当的事件处理函数中更新这个变量。

    import { CdkDrag, CdkDragStart } from '@angular/cdk/drag-drop';
    
    export class MyComponent {
      isDragging = false;
    
      onDragStart(event: CdkDragStart, dragElement: CdkDrag) {
        this.isDragging = true;
      }
    
      onDragEnd(event: CdkDrag, dragElement: CdkDrag) {
        this.isDragging = false;
      }
    }
    
  2. 绑定类名: 在你的HTML模板中,使用[class][ngClass]来根据变量的状态添加或移除类名。

    <div cdkDrag (cdkDragStarted)="onDragStart($event)" (cdkDragEnded)="onDragEnd($event)" [class.dragging]="isDragging" class="drag-box">
      Drag me
    </div>
    
  3. 添加CSS样式: 在你的CSS文件中,定义.dragging类来设置拖动时的样式。

    .dragging {
      background-color: #f00; /* 例如,拖动时的背景颜色 */
      opacity: 0.8;
    }
    

这样,当用户开始拖动元素时,.dragging类将被添加到元素上,当拖动结束时,该类将被移除。

如果你想要更细粒度的控制,比如在拖动过程中添加动画或特定的样式效果,你可以使用CSS的transitionanimation属性来实现平滑的视觉效果。

上述例子展示了如何在Angular CDK拖拽模块中动态添加类名。你可以根据你的具体需求调整这个逻辑。

3. 其它常用方法

Angular CDK的 DragDropModule 提供了许多用于处理拖拽操作的指令和方法。以下是一些常用的方法:

  1. 基础拖拽

    • 使用cdkDrag指令使元素可拖拽。
    • 监听(cdkDragStarted)(cdkDragEnded)事件来处理拖拽开始和结束的逻辑。
  2. 列表排序

    • 结合cdkDragcdkDropList指令实现列表的拖拽排序。
    • 通过监听(cdkDropListDropped)事件并使用moveItemInArray函数来更新数据模型。
  3. 跨列表拖拽

    • 使用cdkDropListConnectedTo属性连接多个cdkDropList实例,实现跨列表的拖拽。
    • 可以使用transferArrayItem函数来处理跨列表的元素转移。
  4. 拖拽方向

    • 使用cdkDragLockAxis属性限制cdkDrag元素沿特定轴向拖拽('x'或'y'轴)。
  5. 自定义拖拽手柄

    • 使用cdkDragHandle指令指定哪个元素可以作为拖拽手柄。
  6. 拖拽预览和占位符

    • 通过cdkDragPreviewcdkDragPlaceholder指令自定义拖拽时的预览元素和占位元素。
  7. 拖拽边界

    • 使用cdkDragBoundary属性限制拖拽元素不能超出特定边界。
  8. 水平列表拖拽

    • 设置cdkDropListOrientationhorizontal来实现水平列表的拖拽排序。
  9. 混合方向拖拽(从Angular Material v18.1.0开始支持):

    • 设置cdkDropListOrientationmixed来实现可以垂直和水平拖拽的列表。
  10. 拖拽动画

    • 通过定义transition动画,为拖拽排序和拖拽到最终位置添加动画效果。
  11. 拖拽禁用

    • 使用cdkDragDisabledcdkDropListDisabled属性来禁用特定的拖拽元素或拖拽列表。
  12. 拖拽进入预测

    • 使用cdkDropListEnterPredicate来定义哪些元素可以进入拖拽列表。

更多内容敬请参考 Drag and Drop | Angular Material