0
点赞
收藏
分享

微信扫一扫

Angular-DragDrop(二):解决使用angular-draggable-droppable插件拖拽穿透冒泡事件问题


先看下问题展示吧

  • 问题描述:
  • 问题展示
  • 蓝色区域
    -
  • Angular-DragDrop(二):解决使用angular-draggable-droppable插件拖拽穿透冒泡事件问题_数据_02

  • 绿色区域

安装使用​​angular-draggable-droppable​

  • 安装
  • ​npm i angular-draggable-droppable​
  • ​yarn add angular-draggable-droppable​
  • 基本使用

<div mwlDraggable [dropData]="{ data: 'this is a data!!!' }">Drag me!</div>
<div mwlDroppable (drop)="onDrop($event)">
<span [hidden]="droppedData">Drop here</span>
<span [hidden]="!droppedData">
Item dropped here with data: "{{ droppedData | json }}"!
</span>
</div>

import { DragAndDropModule } from 'angular-draggable-droppable';

imports: [DragAndDropModule],

droppedData: any;
onDrop(data){
console.log(data)
this.droppedData = data.dropData;
}

  • 展示

问题代码

  • 目录结构
  • 从​​drag组件​​​向​​drop组件​​​内拖入数据
  • Angular-DragDrop(二):解决使用angular-draggable-droppable插件拖拽穿透冒泡事件问题_angular_03

  • ​Drag-Drop/drop/drop.component.html​​ 存在两层拖拽目标容器

<div mwlDroppable
(drop)="onDrop($event)">
<pre>Main Data = {{mainData | json}}</pre>

<div mwlDroppable
(drop)="onDropPart($event)">
<pre>Part Data = {{partData | json}}</pre>
</div>

</div>

mainData: any = [];                             // 外层主容器
partData: any = []; // 里层副容器
/**
* 主容器拖拽获取数据
* @param data:数据
*/
onDrop(data: DropEvent<any>) {
console.log('Main Data', data);
this.mainData.push(data);
}

/**
* 副容器拖拽获取数据
* @param data:数据
*/
onDropPart(data: DropEvent<any>) {
console.log('Part Data', data);
this.partData.push(data);
}

解决方案

  • 添加​​pointerup​​事件进行组织冒泡行为, 请忽略这个方法的第二个参数

<div mwlDroppable
(drop)="onDrop($event)"
(pointerup)="onPointerMain($event, 'Main Up')">

<div>
<pre>Main Data = {{mainData | json}}</pre>
</div>

<div mwlDroppable
(drop)="onDropPart($event)"
(pointerup)="onPointerPart($event, 'Part Up')">
<pre>Part Data = {{partData | json}}</pre>
</div>

</div>

/**
* 主容器的拖拽事件监听
* @param ev :事件
* @param desc :描述
*/
onPointerMain(ev: PointerEvent, desc: string) {
console.log(desc, ev);
ev.preventDefault();
ev.stopPropagation();
}

/**
* 副容器的拖拽事件监听
* @param ev :事件
* @param desc :描述
*/
onPointerPart(ev: PointerEvent, desc: string) {
console.log(desc, ev);
ev.preventDefault();
ev.stopPropagation();
}

  • 测试以上代码后发现冒泡穿透事件已被阻止,但因为​​drop​​事件并未作出修改导致以上代码目前并没有卵用
  • 修改​​drop​​方法,定义一个临时存储拖拽数据的变量

private tempData: DropEvent<any>;

/**
* 主容器拖拽获取数据
* @param data:数据
*/
onDrop(data: DropEvent<any>) {
console.log('Main Data', data);
this.tempData = data;
}

/**
* 副容器拖拽获取数据
* @param data:数据
*/
onDropPart(data: DropEvent<any>) {
console.log('Part Data', data);
this.tempData = data;
}

  • 然后发现这样修改后只是存了一下变量,但是还没有使用
  • 使用临时变量​​tempData​

/**
* 主容器的拖拽事件监听
* @param ev :事件
* @param desc :描述
*/
onPointerMain(ev: PointerEvent, desc: string) {
console.log(desc, ev);
ev.preventDefault();
ev.stopPropagation();
this.mainData.push(this.tempData);
}
/**
* 副容器的拖拽事件监听
* @param ev :事件
* @param desc :描述
*/
onPointerPart(ev: PointerEvent, desc: string) {
console.log(desc, ev);
ev.preventDefault();
ev.stopPropagation();
this.partData.push(this.tempData);
}

  • 这时候发现添加的数据,第一次添加的是​​null​​​,因为​​pointerup​​​是监听鼠标抬起事件,当抬起鼠标时这一时刻​​tempData​​​变量还并没有数据,所以是​​null​
  • 解决:

/**
* 主容器的拖拽事件监听
* @param ev :事件
* @param desc :描述
*/
onPointerMain(ev: PointerEvent, desc: string) {
console.log(desc, ev);
ev.preventDefault();
ev.stopPropagation();
setTimeout(_ => {
this.mainData.push(this.tempData);
});
}
/**
* 副容器的拖拽事件监听
* @param ev :事件
* @param desc :描述
*/
onPointerPart(ev: PointerEvent, desc: string) {
console.log(desc, ev);
ev.preventDefault();
ev.stopPropagation();
setTimeout(_ => {
this.partData.push(this.tempData);
});
}

  • 这时候数据的冒泡穿透问题基本解决了,但是因为​​pointerup​​​监听的是容器内鼠标的抬起事件,这时候不拖动数据每次只在容器内点击鼠标在抬起都会向容器内添加一条数据,所以应该在每次获取完成数据后将​​tempData​​​内的数据清空,并根据​​tempData​​是否为空在判断是否向容器内添加数据
  • 修改完善:

/**
* 主容器的拖拽事件监听
* @param ev :事件
* @param desc :描述
*/
onPointerMain(ev: PointerEvent, desc: string) {
console.log(desc, ev);
ev.preventDefault();
ev.stopPropagation();
setTimeout(_ => {
if (this.tempData) {
this.mainData.push(this.tempData);
this.tempData = null;
}
});
}
/**
* 副容器的拖拽事件监听
* @param ev :事件
* @param desc :描述
*/
onPointerPart(ev: PointerEvent, desc: string) {
console.log(desc, ev);
ev.preventDefault();
ev.stopPropagation();
setTimeout(_ => {
if (this.tempData) {
this.partData.push(this.tempData);
this.tempData = null;
}
});
}

最终展示

Angular-DragDrop(二):解决使用angular-draggable-droppable插件拖拽穿透冒泡事件问题_typescript_04

  • 注意:由于判断了临时数据的是空与否,这时候不去阻止冒泡也能实现功能,但是问题主要还是出现在因为冒泡的影响上,所以冒泡事件还是阻止比较好,这样也不会让监听抬起事件执行多次

完整代码

  • html

<!-- Drag-Drop/drag-drop.component.html -->
<h2>@ Drag Drop Data</h2>
<div nz-row [nzGutter]="[10, 10]">
<div nz-col nzSpan="4">
<div class="ant-alert-warning pad_10">
<app-drag></app-drag>
</div>
</div>
<div nz-col nzSpan="20">
<div class="ant-alert-info min-h_400 pad_10">
<app-drop></app-drop>
</div>
</div>
</div>

<!-- Drag-Drop/drag/drag.component.html -->
<div nz-row [nzGutter]="[10 ,10]">
<ng-container *ngFor="let item of data; let i = index;">
<div nz-col
nzSpan="24"
mwlDraggable
[dropData]="item"
class="z10">
<button nz-button nzBlock nzSize="small" nzType="dashed">{{item.key}}</button>
</div>
</ng-container>
</div>

<!-- Drag-Drop/drop/drop.component.html -->
<div class="h-100 flex"
mwlDroppable
(drop)="onDrop($event)"
(pointerup)="onPointerMain($event, 'Main Up')">

<div class="flex1 pad_r_10">
<nz-alert nzType="info" nzMessage="Main 请拖拽到此区域"></nz-alert>
<pre class="pad_10">Main Data = {{mainData | json}}</pre>
</div>

<div class="flex1 ant-alert-success min-h_400 pad_10"
mwlDroppable
(drop)="onDropPart($event)"
(pointerup)="onPointerPart($event, 'Part Up')">
<nz-alert nzType="success" nzMessage="Part 请拖拽到此区域"></nz-alert>
<pre class="pad_10">Part Data = {{partData | json}}</pre>
</div>

</div>

  • css

/* Drag-Drop/drag-drop.component.css */
.min-h_400{
min-height: 400px;
}
.pad_10{
padding: 10px;
}
.pad_r_10{
padding-right: 10px;
}
.h-100{
height: 100%;
}

.z10{
z-index: 10;
}
.flex{
display: flex;
justify-content: space-between;
align-items: self-start;
}
.flex1{
flex: 1;
}
pre{
margin: 10px 0 0 0;
background-color: #000;
color: #fff;
}

  • ts

// Drag-Drop/drag/drag.component.ts
import {Component, OnInit} from '@angular/core';

@Component({
selector: 'app-drag',
templateUrl: './drag.component.html',
styleUrls: ['../drag-drop.component.css']
})
export class DragComponent implements OnInit {
data: any = [
{
key: 'Data 01'
},
{
key: 'Data 02'
}
];
constructor() {
}

ngOnInit(): void {
}
}

// Drag-Drop/drop/drop.component.ts
import {Component, OnInit} from '@angular/core';
import {DropEvent} from 'angular-draggable-droppable';

@Component({
selector: 'app-drop',
templateUrl: './drop.component.html',
styleUrls: ['../drag-drop.component.css']
})
export class DropComponent implements OnInit {

mainData: any = []; // 外层主容器
partData: any = []; // 里层副容器
private tempData: DropEvent<any>;

constructor() {
}

ngOnInit(): void {
}

/**
* 主容器拖拽获取数据
* @param data:数据
*/
onDrop(data: DropEvent<any>) {
console.log('Main Data', data);
this.tempData = data;
}

/**
* 副容器拖拽获取数据
* @param data:数据
*/
onDropPart(data: DropEvent<any>) {
console.log('Part Data', data);
this.tempData = data;
}

/**
* 主容器的拖拽事件监听
* @param ev :事件
* @param desc :描述
*/
onPointerMain(ev: PointerEvent, desc: string) {
console.log(desc, ev);
ev.preventDefault();
ev.stopPropagation();
setTimeout(_ => {
if (this.tempData) {
this.mainData.push(this.tempData);
this.tempData = null;
}
});
}

/**
* 副容器的拖拽事件监听
* @param ev :事件
* @param desc :描述
*/
onPointerPart(ev: PointerEvent, desc: string) {
console.log(desc, ev);
ev.preventDefault();
ev.stopPropagation();
setTimeout(_ => {
if (this.tempData) {
this.partData.push(this.tempData);
this.tempData = null;
}
});
}

}


举报

相关推荐

0 条评论