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

递归组件中JSON键映射拖拽功能异常问题排查

JSON拖拽键映射功能问题修复

我正在实现两个JSON之间的拖拽键映射功能,用递归组件JsonViewerComponent展示JSON结构,通过isSourceJson标识区分源/目标:源JSON显示可拖拽的扁平化键,目标JSON显示放置区域。目前碰到两个具体问题:

  1. 可拖拽元素的dragstart事件能触发,但UI没有拖拽视觉效果;换成drag事件或移除事件绑定后,UI拖拽显示正常。
  2. 目标JSON的放置区域dragover事件能正常触发,但drop事件完全没响应。

问题1修复:dragstart事件导致UI无拖拽反馈

问题根源有两个:一是模板里绑定的是drag事件而非dragstart,二是dragstart事件处理逻辑没有让浏览器生成默认拖拽UI。

修复步骤:

  • 把模板中可拖拽元素的(drag)替换为(dragstart),并传入事件对象和当前扁平化键值
  • 在dragstart事件处理中正确设置dataTransfer数据,让浏览器识别拖拽行为并生成默认UI

问题2修复:drop事件无响应

drop事件不触发的核心原因是dragover事件中没有阻止默认行为——浏览器默认会阻止拖拽到非标准区域,必须调用event.preventDefault()才能启用drop事件。另外drop事件中也需要阻止默认行为,避免浏览器尝试打开拖拽的文本数据。


修改后的核心代码

json-viewer.component.html

<ng-container *ngIf="data">
    <ng-container *ngIf="isObject(data)">
        <span>{{'{'}}</span><br>
        <div *ngFor="let item of getFormattedData(data)" [style.marginLeft.px]="20">
            <span>{{item.key}}: </span><app-json-viewer [data]="item.value" [previousKey]="previousKey+item.key+'.'" [isSourceJson]="isSourceJson"></app-json-viewer>
        </div>
        <span>{{'}'}}</span>
    </ng-container>
    <ng-container *ngIf="isArray(data)">
        <span>{{'['}}</span><br>
        <div *ngFor="let item of data" [style.marginLeft.px]="20">
            <app-json-viewer [data]="item" [previousKey]="previousKey" [isSourceJson]="isSourceJson"></app-json-viewer>
        </div>
        <span>{{']'}}</span><br>
    </ng-container>
    <ng-container *ngIf="!isObject(data) && !isArray(data)">
        <span>{{data}},</span>
        <ng-container *ngIf="isSourceJson">
            <!-- 替换drag为dragstart,传递事件和键值 -->
            <span class="draggable" draggable="true" (dragstart)="onDragStart($event, previousKey.slice(0, -1))">{{previousKey.slice(0, -1)}}</span>
        </ng-container>
        <ng-container *ngIf="!isSourceJson">
            <span class="drop-area" (dragover)="onDragOver($event)" (drop)="onDrop($event)">{{ sourceKey || '拖拽到这里' }}</span>
        </ng-container>
    </ng-container>
</ng-container>

json-viewer.component.ts

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-json-viewer',
  templateUrl: './json-viewer.component.html',
  styleUrls: ['./json-viewer.component.less']
})
export class JsonViewerComponent {
  @Input() data: any;
  @Input() previousKey: string = '';
  @Input() isSourceJson: boolean = true;

  sourceKey?: string;

  isObject(val: any): boolean {
    return val && typeof val === 'object' && !Array.isArray(val);
  }

  isArray(val: any): boolean {
    return Array.isArray(val);
  }

  getFormattedData(data: any): Array<{ key: string, value: any }> {
    let result = [];
    for (let key in data) {
      if (data.hasOwnProperty(key)) {
        result.push({ key, value: data[key] });
      }
    }
    return result;
  }

  onDragStart(event: DragEvent, key: string) {
    console.log("拖拽开始", key);
    // 必须设置dataTransfer数据,否则浏览器可能不触发后续拖拽流程
    event.dataTransfer!.setData('text/plain', key);
    event.dataTransfer!.effectAllowed = "copyMove";
  }

  onDragOver(event: DragEvent) {
    // 阻止默认行为是触发drop事件的核心
    event.preventDefault();
    event.dataTransfer!.dropEffect = "copyMove";
  }

  onDrop(event: DragEvent) {
    console.log('拖拽完成');
    // 阻止默认行为,避免浏览器打开拖拽的文本内容
    event.preventDefault();
    const data = event.dataTransfer!.getData('text/plain');
    if(data) this.sourceKey = data;
    event.dataTransfer!.clearData();
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 18:40:53