You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular拖拽复制:实现拖拽时不临时移除原容器元素

Angular CDK拖拽复制时保留原容器元素的实现方案

要实现拖拽复制时原容器元素不被临时移除,核心是把默认的"移动"逻辑改成"复制"逻辑,同时调整拖拽过程中的视觉表现,避免原元素被占位符替换而消失。以下是基于你提供的测试代码的具体修改步骤:


1. 修正HTML结构与事件绑定

  • 修正*ngFor的变量名(避免和数组名冲突)
  • 给cdkDrag添加拖拽开始(cdkDragStarted)和拖拽结束(cdkDragStopped)事件,用来记录拖拽元素和恢复样式

修改后的HTML:

<div class="container">
  <h2>Movies</h2>
  <div 
    cdkDropList 
    #moviesList="cdkDropList" 
    [cdkDropListData]="MoviesList"
    [cdkDropListConnectedTo]="[doneMovieList]" 
    class="movie-list" 
    (cdkDropListDropped)="onDrop($event)">
    <div class="movie-block" *ngFor="let movie of MoviesList" cdkDrag 
         (cdkDragStarted)="onDragStarted($event, movie)" 
         (cdkDragStopped)="onDragStopped($event)">
      {{movie}}
    </div>
  </div>
</div>
<div class="container">
  <h2>Movies Watched</h2>
  <div 
    cdkDropList 
    #doneMovieList="cdkDropList" 
    [cdkDropListData]="MoviesWatched"
    [cdkDropListConnectedTo]="[moviesList]" 
    class="movie-list" 
    (cdkDropListDropped)="onDrop($event)">
    <div class="movie-block" *ngFor="let movie of MoviesWatched" cdkDrag>{{movie}}</div>
  </div>
</div>

2. 修改TS逻辑,实现复制而非转移

  • 添加变量记录当前拖拽的元素
  • 在onDrop里把transferArrayItem换成复制操作(只添加到目标容器,不删除原容器元素)
  • 拖拽开始/结束时维护原元素的显示状态

修改后的TS:

import { Component } from '@angular/core';
import { CdkDragDrop, CdkDragStart, CdkDragEnd, moveItemInArray } from '@angular/cdk/drag-drop';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  MoviesList: any = [
    'The Far Side of the World',
    'Morituri',
    'Napoleon Dynamite',
    'Pulp Fiction',
    'Blade Runner',
    'Cool Hand Luke',
    'Heat',
    'Juice'
  ];
  MoviesWatched: any = [];
  draggedMovie: any;

  onDragStarted(event: CdkDragStart, movie: any) {
    this.draggedMovie = movie;
    // 确保原元素在拖拽过程中保持可见
    event.source.element.nativeElement.style.opacity = '1';
  }

  onDragStopped(event: CdkDragEnd) {
    this.draggedMovie = null;
    // 恢复原元素默认样式
    event.source.element.nativeElement.style.opacity = '';
  }

  onDrop(event: CdkDragDrop<any[]>) {
    if (event.previousContainer === event.container) {
      // 同容器内拖拽仍保持排序功能
      moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
    } else {
      // 跨容器时执行复制操作,而非转移
      if (this.draggedMovie) {
        event.container.data.splice(event.currentIndex, 0, this.draggedMovie);
      }
    }
  }  
}

3. 调整CSS,隐藏占位符避免原位置空出

默认的cdk-drag-placeholder会替换原元素并设为透明,导致原容器出现空白,直接隐藏占位符即可:

.wrapper {
  margin: 25px auto;
  max-width: 600px;
  text-align: center;
  padding: 0 20px;
}
.container {
  width: 45%;
  margin: 0 25px 25px 0;
  display: inline-block;
  vertical-align: top;
}
.movie-list {
  width: 80%;
  border: solid 1px #ccc;
  min-height: 60px;
  display: inline-block;
  background: white;
  border-radius: 4px;
  overflow: hidden;
  margin-top: 25px;
}
.movie-block {
  padding: 20px 10px;
  border-bottom: solid 1px #ccc;
  color: rgba(0, 0, 0, 0.87);
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
  cursor: move;
  background: white;
  font-size: 14px;
}
.cdk-drag-preview {
  box-sizing: border-box;
  border-radius: 4px;
  box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
    0 8px 10px 1px rgba(0, 0, 0, 0.14),
    0 3px 14px 2px rgba(0, 0, 0, 0.12);
}
/* 修改占位符样式,直接隐藏 */
.cdk-drag-placeholder {
  display: none;
}
.cdk-drag-animating {
  transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
.movie-block:last-child {
  border: none;
}
.movie-list.cdk-drop-list-dragging .movie-block:not(.cdk-drag-placeholder) {
  transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}

核心原理说明

  1. 避免原元素移除:通过隐藏cdk-drag-placeholder,阻止原元素被占位符替换,同时在拖拽开始时强制原元素保持可见
  2. 复制逻辑替代转移:放弃使用transferArrayItem(该方法会删除原数组元素),改为直接将拖拽元素插入目标数组
  3. 状态维护:通过cdkDragStarted和cdkDragStopped记录拖拽元素并恢复样式,确保交互过程的一致性

内容的提问来源于stack exchange,提问作者Nakul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 22:45:37