DOM更改在我的Angular2组件中按顺序执行

时间:2016-07-07 11:17:00

标签: dom angular

我有一个Angular2组件,用于更新我正在注释并允许用户编辑的导入的HTML文件。为此,我使用纯HTML5直接更新DOM。单击时,应该将一个类添加到单击的DOM元素中。在浏览器(Linux上的FF和Chrome)中,它会暂时添加 - 这意味着如果我立即打印节点,我会看到该类,但是在我退出该函数并打印后我没有。 Inspect Element显示元素已更新为< .... class>单击元素时没有值。 当我在没有Angular的情况下实现它时,这工作正常。 我尝试直接DOM操作(使用classList.add和x.className = y),angular的渲染器,并通过NgZone运行代码,并且都具有相同的效果。有人能告诉我为什么会发生这种情况以及我能做些什么来解决这个问题? 注意:这是(应该是)一个简单的内部工具 - 此时我需要快速修复(尽管也欢迎其他建议)。 (这里没有完全实现的代码中一些不相关的部分。)

import { Component, OnInit, NgZone } from "@angular/core";
import { Http, Headers, RequestOptions } from "@angular/http";

@Component({
    selector: "editor",
    templateUrl: `editor/starterDemo.html`
})
export class EditorComponent implements OnInit {

    ngOnInit() {
        this.fixImagePaths();
        this.annotate();
    }

    constructor(public http: Http, public zone: NgZone) { }
    //    constructor(public http: Http, public renderer: Renderer) { }

    fixImagePaths = () => {
        const els = document.querySelectorAll('img');
        for (let i: number = 0, el: any; (el = els[i]); i++) {
            el.src = 'editor/' + el.getAttribute('src');
        }

    }

    annotate = () => {
        document.body.addEventListener('dragover', this.drag_over);
        document.body.addEventListener('click', this.selectNone);
        document.body.addEventListener('keydown', this.keyDown);

        const els = document.querySelectorAll('img, .box');
        for (let i: number = 0, el: any; (el = els[i]); i++) {
            el.draggable = true;
            el.addEventListener('dragstart', this.drag_start);
            el.addEventListener('click', this.selectItem);
        }
    }

    selectItem = (event) => {
        console.log("select item!");
        this.selectNone();
//        this.zone.run(() => {
            event.target.closest('[draggable]').classList.add('dragme');
//        });
        //        this.renderer.setElementClass(event.target.closest('[draggable]').nativeElement, 'dragme', true);
         //        console.log(event.target.closest('[draggable]'));
        //        console.log(event.target.closest('[draggable]').classList);
        //        console.log(event.target.closest('[draggable]').classList.contains('dragme'));
        console.log(this.selected());
        return false;
    }

    selectNone = () => {
        this.selected() && this.selected().classList.remove('dragme');
    }

    selected = (): any => document.getElementsByClassName('dragme')[0];
}

HTML:

<div class='box'
    style="background-color: white; position: absolute; top: 847px; left: 842px; z-index: 20; height: 118px; width: 351px"></div>

<img src="Screenshot1.png"
    style="position: absolute; top: 0px; left: -1px" />
<img src="Screenshot2.png"
    style="position: absolute; top: 913px; left: 0px; z-index: 2"/>
<img src="Screenshot3.png"
    style="position: absolute; top: 1768px; left: 0px" />

<div style="height: 2000px">&nbsp;</div>

1 个答案:

答案 0 :(得分:0)

我只是想出了问题(经过数小时的痛苦)。似乎在linux chrome上,返回false并不足以阻止事件传播,因此click事件在addClass调用之前和之后运行了两次。由于click事件在开头有一个selectNone()(清除现有的选定项),因此在添加类之前和之后运行了selectNone()。我添加了event.preventDefault();和event.stopPropagation();到我的事件处理程序。 我希望这有助于某人。