【问题标题】:Accessing Directive scope with in HTML element event handler在 HTML 元素事件处理程序中访问指令范围
【发布时间】:2018-10-26 12:16:11
【问题描述】:

我创建了一个 Directive 来使用一个元素作为带有原生 HTML 拖放的“dropzone”

指令来源

import { Directive, ElementRef, OnInit, Output, EventEmitter, ViewChild } 
from '@angular/core';
import { environment } from 'src/environments/environment';

@Directive({
    selector: '[app-drop-zone]'
})
export class DropzoneDirective implements OnInit {    
    @Output('outbound-listener') outBoundListener = new EventEmitter();    

    constructor(private e: ElementRef) {        
        e.nativeElement.ondrop = this.drop;
        e.nativeElement.ondragover = this.dragOver;
        e.nativeElement.ondragenter = this.dragEnter;
        e.nativeElement.ondragleave = this.dragLeave;            
    }

    ngOnInit(): void { }

    private drop(event: any){ 

        let files: File[] = []; // temprary cache for dropped files

        if (event.stopPropagation) {
           event.stopPropagation(); // Stops some browsers from redirecting.
        }

        event.currentTarget.classList.remove('over');    // remove the 
        dotted background, once user release the content (drop-end)

       // process dropped items
       if(event.dataTransfer.items){
       for(let i = 0; i< event.dataTransfer.items.length; i++){
           if(event.dataTransfer.items[i].kind == "file"){
               files.push(event.dataTransfer.items[i].getAsFile());
           }
       }

       if(files.length > 0){
           this.outBoundListener.emit({ type: 
           environment.component_events.INIT_FILE_UPLOAD, data: files});              
       }
    }
    return false;
 }

 private dragOver(e){
      if(e.preventDefault)
          e.preventDefault();    

      e.dataTransfer.dropEffect = 'move';
      return false;
 }

 private dragEnter(event: any) {     
    event.currentTarget.classList.add('over');    
 }

 private dragLeave(event: any) {    
    event.currentTarget.classList.remove('over');    
 }
}

** 请忽略代码格式问题 :-(

问题这里是,在方法 'drop' 中,我想访问 Directive Class prop outBoundListener 这是一个 EventEmitter 但我无法通过 this 调用它

对此的任何帮助将不胜感激..

【问题讨论】:

  • 应该可以使用this.outBoundListener访问。
  • ^ 这实际上是我的问题。无法访问,this这里指的是所有者(被调用者)
  • 奇怪的是,“JS 闭包标准”在这里没有发挥作用。如果您使用function drop 语法,就会出现这种情况,但是您声明它的方式,this 应该绝对指向您的对象,而不是函数。你得到的具体错误是什么?
  • 只是“无法读取属性outboundListener of undefined”。
  • ^ 更新了我的提交。这种情况的解决办法是什么?

标签: angular closures angular6


【解决方案1】:

当从 TypeScript 代码调用时,您所拥有的绝对应该可以工作,因为 TypeScript/ES6 this 语义对于箭头函数有些不同。您可以阅读更多关于 here 的信息,其中有一整节专门用于讨论热乱七八糟的问题,即 this

这里的问题不是this指的是所有者或被调用者,而是DOM元素。您可以通过在 drop 函数顶部调用 console.log(this) 来验证这一点。

事情变得不正常的原因是,这个函数不是从 ES6 或 TypeScript 代码调用的,而是从 DOM 事件处理程序调用的。要强制它保留this,您可以使用bind 函数。

constructor(private e: ElementRef) {        
    e.nativeElement.ondrop = this.drop.bind(this);
    e.nativeElement.ondragover = this.dragOver.bind(this);
    e.nativeElement.ondragenter = this.dragEnter.bind(this);
    e.nativeElement.ondragleave = this.dragLeave.bind(this);
}

请注意,this 是您的对象实例,您现在通过使用提供的 this 值创建一个新函数来强制实现这种情况,根据 the MDN explanation

替代方法是使用内联箭头函数。

constructor(private e: ElementRef) {        
    e.nativeElement.ondrop = event => this.drop(event);
    e.nativeElement.ondragover = event => this.dragOver(event);
    e.nativeElement.ondragenter = event => this.dragEnter(event);
    e.nativeElement.ondragleave = event => this.dragLeave(event); 
}

在这里它起作用了,因为箭头函数保留了this,如前所述。

【讨论】:

    猜你喜欢
    • 2018-08-18
    • 2013-05-22
    • 2022-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-24
    • 1970-01-01
    相关资源
    最近更新 更多