2016-03-02 18 views
6

私はカスタムのドラッグアンドドロップディレクティブを実装しようとしています。それは動作しますが、それは非常に遅いです、私は遅いことが以前にこの遅さに遭遇したことがないのでAngular 2に追跡することができると思います。遅いのは、dragoverまたはdragイベント(頻繁に送信されるイベント)にイベントリスナーをアタッチしたときに発生します。何もしない場合でも、falseが返されます。ここで角度2のドラッグ&ドロップディレクティブが極端に遅い

は私の指示のコードは次のとおりです。あなたは私がやっているすべては黄色で、ドラッグされた要素を強調している見ることができるように

.my-log.my-dragging-over { 
    background-color: yellow; 
} 

:ここ

import {Directive, ElementRef, Inject, Injectable} from 'angular2/core'; 

declare var jQuery: any; 
declare var document: any; 

@Directive({ 
    selector: '.my-log', 
    host: { 
     '(dragstart)': 'onDragStart($event)', 
     '(dragover)': 'onDragOver($event)', 
     '(dragleave)': 'onDragLeave($event)', 
     '(dragenter)': 'onDragEnter($event)', 
     '(drop)': 'onDrop($event)', 
    } 
}) 
@Injectable() 
export class DraggableDirective { 
    refcount = 0; 
    jel; 

    constructor(@Inject(ElementRef) private el: ElementRef) { 
     el.nativeElement.setAttribute('draggable', 'true'); 
     this.jel = jQuery(el.nativeElement); 
    } 

    onDragStart(ev) { 
     ev.dataTransfer.setData('Text', ev.target.id); 
    } 

    onDragOver(ev) { 
     return false; 
    } 

    onDragEnter(ev) { 
     if (this.refcount === 0) { 
      this.jel.addClass('my-dragging-over'); 
     } 
     this.refcount++; 
    } 

    onDragLeave(ev) { 
     this.refcount--; 
     if (this.refcount === 0) { 
      this.jel.removeClass('my-dragging-over'); 
     } 
    } 

    onDrop(ev) { 
     this.jel.removeClass('my-dragging-over'); 
     this.refcount = 0; 
    } 
} 

は、関連するスタイルシートの抜粋です。そして、私がdragoverイベントを処理していないときは速く動作しますが、私はが落としをサポートする必要があります。 dragoverイベントを処理すると、すべてが耐え難いレベルにまで減速します!!

EDIT私は、角度ベータ2.0.0-beta.8を使用しています

EDIT#2私はChromeのプロファイラーを使用してコードをプロファイリングしようとした、これらは結果である:

Imgur

は、

マークされた行を見て、それは奇妙に疑わしいです...

EDIT#3問題が見つかりました:実際には角度2の変化の検出によるものです。私の場合のドラッグアンドドロップ操作は、多くのバインディングとディレクティブを持つ非常に密集したページで行われます。私が与えられたリスト以外の全てをコメントアウトしたとき、それは再び速く働いた...今、私はあなたの助けを必要としてこれに解決策を見つける!

EDIT#4は、問題が実際に検出を変更したが、障害が角度のコードではなく、むしろ自分の非効率的なバインディングではなかった

を解決しました。私はこの種の多くのバインディングを持っていた:

*ngFor="#a of someFunc()" 

このデータは、ドラッグ&ドロップ処理中に変更されなかったにもかかわらず、再びデータが変更またはない、と機能someFuncが再び呼び出さなったしたかどうかわからないことが角度原因と。私は、これらのバインディングをクラスの単純なプロパティを参照するように変更し、その場所に配置されるコードを移動しました。すべてが再び素早く動くようになった!

ありがとうございます!自分の質問に答える

+1

あなたは、問題の原因が何であるかを簡単な言葉で説明できますか?私は問題を読むことから多くを理解することができません... –

+0

おそらくng2とjQueryが混在しているので、ng2 + RxJSだけに頼ってみましたか? http://plnkr.co/edit/LD5FJaI4OOFbKfvhjD4e?p=preview –

+0

これは原因ではありません。申し訳ありませんが、jQueryのすべてのトレースを削除しようとしました。同じ結果。 –

答えて

4

(問題が解決されました)。

遅れの問題は、マークアップで効率の悪いデータバインディングが原因で、Angularがビューモデルで関数を呼び出す時間を浪費していました。1回程度のである(これはデータが変更されたかどうかわからないことがアンギュラ原因

*ngFor="#a of someFunc()" 

、および機能someFunconDragOverのすべての実行後に何度も何度も呼ばなっていた:私はこの種の多くのバインディングを持っていましたドラッグ&ドロップ処理中にデータが変更されていなくても、私は、これらのバインディングをクラスの単純なプロパティを参照するように変更し、その場所に配置されるコードを移動しました。すべてが再び素早く動くようになった!

LLAP!

4

同じ問題でちょっとしたトラブルが発生しました。効率的なngForコードであっても、ドラッグ可能なアイテムが多数ある場合、ドラッグ&ドロップは狂っています。

私にとっては、すべてのドラッグアンドドロップイベントリスナーをAngularの外側でngZoneで実行させてから、ドロップしたときにAngularに戻すようにしました。これにより、Angularは、ドラッグ可能なアイテムを移動するピクセルごとに検出をチェックしないようにします。

を注入:ドロップオン

ngOnInit() { 
    this.ngZone.runOutsideAngular(() => { 
    el.addEventListener('dragenter', (e) => { 
     // do stuff with e or el 
    }); 
... 

import { Directive, ElementRef, NgZone } from '@angular/core'; 
constructor(private el: ElementRef, private ngZone: NgZone) {} 

初期化私は入れなかったとき

は、私は同様の問題があった
el.addEventListener('drop', (e) => { 
    this.ngZone.run(() => { 
     console.log("dropped"); 
    }) 
}) 
+0

最後に解決策! Drag'nDropは、多くのバインディングが関与しているツリー構造で痛いほど遅かった。回転する「ドラゴーヴァー」イベントの10-15秒も例外ではなかった。ありがとうございました。 – passerby

+0

恐ろしい解決策。非常に速いです。 –

0

、また私のドラッグ&ドロップが非常に遅くなりました*ngForの中の複数のドラッグゾーン。

私はこれを、子コンポーネントの変更検出戦略をOnPushに変更して解決しました。

アイテムがドラッグされるたびに、markForCheck()を実行します。

constructor(private changeDetectorRef: ChangeDetectorRef) {} 
 
    
 
// Callback function 
 
public onDrag() { 
 
    this.changeDetectorRef.markForCheck(); 
 
}