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

如何让Angular 8中cdkDrag与mat-grid-list拖拽后保持网格布局?

解决Angular Material mat-grid-list结合cdkDrag后网格布局混乱的问题

我来帮你搞定这个问题!你当前的代码之所以拖拽后无法保持整齐的网格布局,核心原因是DOM结构不符合mat-grid-list的组件规范——mat-grid-list要求直接子元素必须是mat-grid-tile,但你现在用一个带cdkDrag的div包裹了mat-grid-tile,这破坏了mat-grid-list的布局逻辑,导致它无法正确识别并排列tile。

解决方案:调整结构,让cdkDrag直接作用于mat-grid-tile

我们需要修改DOM结构,让mat-grid-list直接作为拖拽容器(cdkDropList),同时把cdkDrag指令直接绑定到mat-grid-tile上,这样既能保留拖拽功能,又能让mat-grid-list维持正常的网格布局。

修改后的完整代码:

app.component.html
<style>
 .mat-grid-tile {
   position: relative; /* 确保拖拽手柄的绝对定位相对于tile本身 */
 }
 .drag-handle { 
   position: absolute; 
   top: 10px; 
   left: 10px; 
   color: #ccc; 
   cursor: move; 
   width: 24px; 
   height: 24px;
   z-index: 10; /* 保证拖拽手柄在tile内容上方 */
 }
</style>

<div cdkScrollable>
 <mat-grid-list 
   cols="4" 
   rowHeight="3:4" 
   style="width: 25%;"
   cdkDropList 
   (cdkDropListDropped)="drop($event)"
 >
   <mat-grid-tile 
     *ngFor="let number of numbers" 
     style="border: 1px solid green;"
     cdkDrag
   >
     {{number}}
     <div class="drag-handle" cdkDragHandle>
       <svg width="24px" fill="currentColor" viewBox="0 0 24 24">
         <path d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z"></path>
         <path d="M0 0h24v24H0z" fill="none"></path>
       </svg>
     </div>
   </mat-grid-tile>
 </mat-grid-list>
</div>
app.component.ts(无需修改,保持原有逻辑即可)
import { Component } from '@angular/core';
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';

@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent {
 title = 'drag-drop';
 numbers: number[] = [];
 
 constructor() {
   for (let i = 0; i < 100; i++) {
     this.numbers.push(i);
   }
 }
 
 drop(event: CdkDragDrop<number[]>) {
   moveItemInArray(this.numbers, event.previousIndex, event.currentIndex);
 }
}

关键修改说明:

  1. 修复DOM结构:将cdkDropList和拖拽触发事件绑定到mat-grid-list本身,同时移除包裹mat-grid-tile的额外div,直接在mat-grid-tile上使用cdkDrag。这样mat-grid-list的直接子元素都是符合要求的mat-grid-tile,能正常按网格规则排列。
  2. 调整样式:给mat-grid-tile添加position: relative,确保拖拽手柄的绝对定位是相对于tile本身,而不是其他父元素。
  3. 保留拖拽逻辑:原有的drop函数无需改动,因为我们依然是通过修改numbers数组的顺序来控制tile的排列,mat-grid-list会根据数组的新顺序自动重新渲染,保持整齐的4列网格布局。

这样修改后,你拖拽tile时,mat-grid-list会始终按照数组顺序维护网格结构,拖拽完成后tile会自动归位到网格的对应位置,完全符合你的预期。

内容的提问来源于stack exchange,提问作者Jørgen Rasmussen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:05:51