组件是一种带模版的指令。指令是超级。

结构型指令(改变布局)和属性型指令(改变外观和行为)。

Renderer2和ElementRef

Angular不提倡直接操作DOM

对于DOM的操作应该通过Renderer2进行。

ElementRef是指向DOM元素的引用

拖拽指令实例

1、新建directive module

$ ng g m directive
CREATE src/app/directive/directive.module.ts (193 bytes)

2, 在指令文件夹下的drag-drop文件夹里新建一个drag和一个drop

$ ng g d directive/drag-drop/drag
$ ng g d directive/drag-drop/drop

3,改一下selector

selector: '[appDrag]'改为
selector: '[app-draggable]'
selector: '[appDrop]'改为
selector: '[app-droppable]'

4,在SharedModule中导入DirectiveModule

import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { MaterialModule } from "../material/material.module";
import { ConfirmDialogComponent } from "./confirm-dialog/confirm-dialog.component";
import { DirectiveModule } from '../directive/directive.module';

@NgModule({
  imports: [CommonModule, MaterialModule, DirectiveModule],
  exports: [CommonModule, MaterialModule, DirectiveModule],
  declarations: [ConfirmDialogComponent],
  entryComponents: [ConfirmDialogComponent]
})
export class SharedModule { }

5,把DirectiveModule中多余的CommonDodule删掉,然后把Drag和Drop两个指令导出

import { NgModule } from '@angular/core';
import { DragDirective } from './drag-drop/drag.directive';
import { DropDirective } from './drag-drop/drop.directive';

@NgModule({
  declarations: [DragDirective, DropDirective],
  exports: [DragDirective, DropDirective],
})
export class DirectiveModule { }

 

6,drag指令

使用@HostListener监听dragstart事件和dragend事件。

使用ElementRef获取元素。

使用Renderer2修改样式。

draggedClass是一个输入型参数。所以selector 为selector: '[app-draggable][draggedClass]'。

app-draggable设置为true就可以拖拽,为false不可拖拽。

  private _isDraggble = false;

  set isDraggable(value){
    this._isDraggble=value;
  }
  get isDraggable(){
    return this._isDraggble;
  }

给set方法加上@Input(app-draggable)。 这样在调用app-draggable= "true"的时候会调用set方法。

import { Directive, HostListener, Host, ElementRef, Renderer2, Input } from '@angular/core';

@Directive({
  selector: '[app-draggable][draggedClass]'
})
export class DragDirective {

  private _isDraggble = false;

  @Input('app-draggable')
  set isDraggable(value:boolean){
    this._isDraggble=value;
    this.rd.setAttribute(this.el.nativeElement,'draggable',`${value}`);
  }
  get isDraggable(){
    return this._isDraggble;
  }
  @Input()
  draggedClass:string;
  constructor(private el:ElementRef, private rd:Renderer2) { }

  @HostListener('dragstart', ['$event'])
  ondragstart(ev:Event){
    //判断drag元素是不是指令应用的元素发起的
    if(this.el.nativeElement===ev.target){
      this.rd.addClass(this.el.nativeElement, this.draggedClass);//往el上增加一个class
    }

  }

  @HostListener('dragend', ['$event'])
  ondragend(ev:Event){
    if(this.el.nativeElement===ev.target){
      this.rd.removeClass(this.el.nativeElement, this.draggedClass);
    }
  }
}

在task-item组件中使用

//红色dash虚线半透明
.drag-start
{ opacity: 0.5; border: #ff525b dashed 2px; }
<mat-list-item class="container" [@item]="widerPriority" [ngClass]="{
  'priority-normal':item.priority===3,
  'priority-important':item.priority===2,
  'priority-emergency':item.priority===1
}"
  [app-draggable]="true"
  [draggedClass]=" 'drag-start' "
  (click)="onItemClick()">
  ......
</mat-list-item>

7,drop指令

drop要监听dragenter,dragover,dragleave,drop四个事件。

需要改变自己的css。即拖放区域的css。变暗。

Angular 自定义拖拽指令
import { Directive, HostListener, ElementRef, Renderer2, Input  } from '@angular/core';

@Directive({
  selector: '[app-droppable][dragEnterClass]'
})
export class DropDirective {

  @Input()
  dragEnterClass:string;
  constructor(private el:ElementRef, private rd:Renderer2) { }

  @HostListener('dragenter', ['$event'])
  onDragEnter(ev:Event){
    //判断drag元素是不是指令应用的元素发起的
    if(this.el.nativeElement===ev.target){
      this.rd.addClass(this.el.nativeElement, this.dragEnterClass);//往el上增加一个class
    }

  }

  @HostListener('dragover', ['$event'])
  onDragOver(ev:Event){
    //判断drag元素是不是指令应用的元素发起的
    if(this.el.nativeElement===ev.target){
      
    }

  }

  @HostListener('dragleave', ['$event'])
  onDragLeave(ev:Event){
    //判断drag元素是不是指令应用的元素发起的
    if(this.el.nativeElement===ev.target){
      this.rd.removeClass(this.el.nativeElement, this.dragEnterClass);//往el上增加一个class
    }

  }

  @HostListener('drop', ['$event'])
  onDrop(ev:Event){
    //判断drag元素是不是指令应用的元素发起的
    if(this.el.nativeElement===ev.target){
      this.rd.removeClass(this.el.nativeElement, this.dragEnterClass);//往el上增加一个class
    }

  }
}
View Code

相关文章: