setInterval() 问题不访问 Angular2 中的指令函数

Issue with setInterval() not accessing directive function in Angular2

我正在尝试制作一个新闻代码指令,将元素滑过其父元素,以便您可以在字符串太长时读取它。我被卡住了,因为我无法让 setInterval() 函数在其当前范围内调用 moveLeft() 函数,从而将目标元素 (this.node1) 移动到 1px.如果我将元素、函数和参数传递给 setInterval(),则不会调整 DOM,因为我认为该元素超出范围。 如何从 setInterval() 函数调用其当前作用域中的 moveLeft() 函数? 该函数在 setInterval() 函数外部调用时工作正常。

import { Directive, ElementRef, HostListener, Input, Renderer, OnInit } from '@angular/core';

@Directive({ selector: '[ticker]' })
export class TickerDirective implements OnInit {

    currMargin: number;             // i.e.: 4
    newMargin: string;              // i.e.: '4px'
    currInterval: any;              // timeout function variable used to kill the timeout

    container: any;                 // container element
    node1: any;
    node2: any;
    tickerNodes: any[];

    textValue: string;
    @Input('text') text: string;    // display string passed in on an attribute

    constructor(private el: ElementRef, private renderer: Renderer) {  }

    @HostListener('mouseenter') onMouseEnter() {
        // this is where the script is failing
        this.currInterval = setInterval( this.moveLeft(), 100);
    }

    @HostListener('mouseleave') onMouseLeave() {
        clearInterval(this.currInterval);
        this.currMargin = 0;
    }

    moveLeft() { // slide the elements to the left
        this.currMargin -= 1;
        this.newMargin = this.currMargin + 'px';
        this.renderer.setElementStyle(this.node1, 'margin-left', this.newMargin);
    }

    ngOnInit() { // instantiate the elements
        this.currMargin = 0;
        this.textValue = this.el.nativeElement.attributes[2].nodeValue; // sets the text value passed from the component to the directive through an attribute

        // build the container
        this.container = this.renderer.createElement(this.el.nativeElement, 'div');
        this.renderer.setElementClass(this.container, 'ticker-container', true);

        // create the left most element
        this.node1 = this.renderer.createElement(this.container, 'div');
        this.renderer.setElementClass(this.node1, 'ticker-node', true);
        this.renderer.setText(this.node1, this.el.nativeElement.attributes[2].nodeValue);

        // create the right most element
        this.node2 = this.renderer.createElement(this.container, 'div');
        this.renderer.setElementClass(this.node2, 'ticker-node', true);
        this.renderer.setText(this.node2, this.el.nativeElement.attributes[2].nodeValue);

        // render the elementss
        this.tickerNodes = [this.node1, this.node2];
        this.renderer.attachViewAfter(this.container, this.tickerNodes);
    }
}

在您调用

的方法中使用 setInterval()
moveLeft() { // slide the elements to the left
    setInterval(() => {
            this.currMargin -= 1;
            this.newMargin = this.currMargin + 'px';
            this.renderer.setElementStyle(this.node1, 'margin-left', this.newMargin);
    }, 100);    
}

首先,在您的原始版本中,您在间隔设置期间执行 moveleft,而不是提供函数。所以它会在您设置时执行,但不会再执行。

即。 setInterval( this.moveLeft, 100) 而不是 setInterval( this.moveLeft(), 100)

但真正的问题是为 setInterval 提供一个箭头函数,而不是直接提供函数,因为简单地给它函数将改变 this 的上下文(参见 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

例如。 setInterval( () => { this.moveLeft(); }, 100)