Angular 2动态修改DOM元素

时间:2017-03-18 08:20:36

标签: angular

以下是jQuery demo关于我想做的事情。

HTML:

<div class="open-close">
  <div class="open">
    I'm open <span class="opener">opener</span>
  </div>
  <div class="close">
    I'm close <span class="closer">closer</span>
    <div class="open-close">
      <div class="open">
        I'm inner open. <span class="opener">opener</span>
      </div>
      <div class="close">
        I'm inner close. <span class="closer">closer</span>
      </div>
    </div>
  </div>
</div>

jQuery的:

$(function(){
  $(".close").hide();

  $(".opener").click(function() {
    let $this = $(this),
      $parent = $this.closest(".open-close"),
      $close  = $parent.children(".close");

    console.log($parent);

    $close.show();
  });

  $("body").on("click", ".closer", function() {
    let $this = $(this),
      $close  = $this.closest(".close");

    $close.hide();
  });
});

现在,我知道在角色2中使用jQuery不受欢迎,那么Angular 2的做法是什么?

在我的应用程序中,服务器将发送类似于我在演示中提供的HTML,并期望应用程序将隐藏所有“关闭”元素并在“opener”上单击打开它们。目前,这是我的设计。

我认为给出“close”和“open”元素局部变量,而不是'data-id',然后分别使用局部变量“更接近”和“开启”的子元素找到它的开放/关闭具有相同id的计数器部分然后打开/关闭它。

<div class="open" #data-id="1">
  I'm open <span class="opener" (click)="onOpenerClick(data-id)">opener</span>
</div>
<div class="close" #data-id="1">
  I'm close <span class="closer" (click)="onCloserClick(data-id)">closer</span>
  <div class="open" #data-id="2">
    I'm inner open. <span class="opener" (click)="onOpenerClick(data-id)">opener</span>
  </div>
  <div class="close" #data-id="2">
    I'm inner close. <span class="closer" (click)="onCloserClick(data-id)">closer</span>
  </div>
</div>

我真的不知道在Angular 2中这样做。plunker demo是我能得到的。

@Component({
  selector: 'my-app',
  template: `
    <div>
      I'm open. <span (click)="opened=true">opener</span>
      <div *ngIf="opened">
        I'm close <span (click)="opened=false">closer</span>
        <div>
          I'm inner open. <span (click)="opened2=true">opener</span>
          <div *ngIf="opened2">
            I'm inner close <span (click)="opened2=false">closer</span>
          </div>
        </div>
      </div>
    </div>
  `,
  styles: ['span { color : blue }']
})
export class App {
  opened = false;
  opened2 = false;
  name:string;
  constructor() {
    this.name = 'Angular2'
  }
}

但HTML来自服务器。我是否必须以编程方式附加'open'~'openningN'?我希望子元素可以设置其最近的父元素的“已打开”状态。或者有更简单的方法吗?

1 个答案:

答案 0 :(得分:0)

我找到了三种方法。

  1. ElementRef ... plnkr demo
  2. Renderer ... plnkr demo
  3. DomSanitizer ... plnkr demo
  4. ElementRef不安全,根据Angular Documentation使代码与Web Worker不兼容。

    ElementRef

    ElementRef.nativeElement返回您可以像在JavaScript中一样应用事件的本机元素。

    this.el.nativeElement.onclick = function() {
      alert('hi');
    }
    

    javascript相比:

    document.getElementById('target').onclick = function() {
       alert('hi');
    }
    

    渲染

    Angular建议Renderer不要使用ElementRef“看一下Renderer,它提供了可以安全使用的API,即使不支持直接访问本机元素也是如此”来自ElementRef文档。

    let target_el = this.el.nativeElement;
    
    this.renderer.listen(target_el, "click", function() {
      alert('hi..');
    });
    

    从演示中可以看出,ElementRef示例和Renderer示例中的this.el是相同的。

    • 老实说,当他们使用相同的this.el时,我不知道如何使用渲染器更安全。但我假设使用像renderer.listen这样的渲染器方法将事件附加到DOM,通知Angular注意到target_el的输入或者某些东西,而DIRECT访问DOM则没有机会通知Angular。如果你知道它是如何工作的,请评论。我很乐意编辑问题。

    DOM Sanitizer

    使用bypassSecurityTrustHtml来阻止Angular剥离的某些属性。 Angular剥离角度事件出价和Html事件属性。您可以尝试在上面的演示中评论bypassSecurityTrustHtml,它会为您提供

      

    警告:清理HTML会剥离一些内容(请参阅http://g.co/ng/security#xss)。

    在我的情况下,因为我从服务器获取HTML,所以在执行此操作之前我不得不等待一个滴答:

    .subscribe( html => {
        setTimeout( () => {
            this.html_area = html;
    
            // do dynamically adding event thing
        )}
    })