Angular cdkDrag如何禁止点击子Node元素触发父容器拖拽
最优实现方案
方案1:使用CDK原生cdkDragStartPredicate判定(推荐)
这是Angular CDK拖拽模块原生提供的能力,无需额外插入DOM元素,也不会出现层级冲突问题,是性能最优、逻辑最清晰的实现方式。
模板代码调整
移除原来多余的.example-handle透明层元素,给拖拽容器绑定判定函数:
<div class="chart-container" #wrapper cdkDrag [cdkDragStartPredicate]="canDragStart"> <ng-container *ngFor="let node of nodes; let i = index"> <div class="box" [id]="node.id" [ngClass]="{ target: node.type === 'target' }" [style.top.px]="node?.uiPosition?.top || 20" [style.left.px]="node?.uiPosition?.left || 20" > <div class="node"> {{ 'Node' + (i + 1) }} </div> </div> </ng-container> </div>
组件逻辑代码
在组件类中添加拖拽起始判定函数,点击目标为Node元素时直接禁止拖拽触发:
import { CdkDragStart } from '@angular/cdk/drag-drop'; // 组件类内部代码 canDragStart = (event: MouseEvent | TouchEvent) => { const clickTarget = event.target as HTMLElement; // 点击目标是box/node元素及其子元素时,禁止拖拽触发 return !clickTarget.closest('.box, .node'); }
方案2:低版本兼容方案(阻止事件冒泡)
如果使用的Angular版本较低不支持cdkDragStartPredicate,可以直接给Node元素阻止鼠标/触摸事件冒泡,避免事件传递到父容器触发拖拽:
<div class="box" [id]="node.id" [ngClass]="{ target: node.type === 'target' }" [style.top.px]="node?.uiPosition?.top || 20" [style.left.px]="node?.uiPosition?.left || 20" (mousedown)="$event.stopPropagation()" (touchstart)="$event.stopPropagation()" > <div class="node"> {{ 'Node' + (i + 1) }} </div> </div>
这种方案也无需额外添加透明层,仅需要给Node元素加两个事件绑定即可。
原有实现的问题
你当前用的透明handle层方案容易出现z-index层级冲突,一旦层级设置错误要么导致Node元素无法响应点击,要么拖拽功能失效,还额外增加了无意义的DOM节点,维护成本更高,更推荐使用上面两种原生方案。
内容的提问来源于stack exchange,提问作者Kamya Kashyap
相关产品推荐
相关产品推荐

