简体   繁体   English

为什么 addClass 对 Angular 中的 DOM 元素不起作用?

[英]Why addClass does not work for DOM element in Angular?

I have DOM component:我有 DOM 组件:

<app-ui-element-block (click)=do($event)></app-ui-element-block>

Method is:方法是:

public do($event){ 
   const elms = document.getElementsByTagName('app-ui-element-block');

        for (let i = 0; i < elms.length; i++) {
            elms[i].classList.remove('active');
        }

        $event.target.classList.add('active');
}

Why I can not set class for selected element DOM as component?为什么我不能将选定元素 DOM 的 class 设置为组件?

Why not use a more "angular way".为什么不使用更“有角度的方式”。 You can use the ngClass directive instead.您可以改用ngClass指令。

<app-ui-element-block [ngClass]="{'active': isActive}" (click)="isActive=true"></app-ui-element-block>

Then you just need a field in your root component named isActive .然后你只需要在你的根组件中有一个名为isActive的字段。 If you have multiple items then you could either use an array or an indexer or something similar.如果您有多个项目,那么您可以使用数组或索引器或类似的东西。

So you have a component named UiElementBlock , and you want this to have a class or not:因此,您有一个名为UiElementBlock的组件,并且您希望它是否具有 class :

If these are placed using an *ngFor , you can use the looped element as indicator (or something else):如果这些是使用*ngFor放置的,您可以使用循环元素作为指示符(或其他东西):

<app-ui-element-block
  *ngFor="let block of blocks"
  [class.active]="block === active"
  (click)="active = block">
</app-ui-element-block>

In your parent component you need to define this active :在您的父组件中,您需要定义这个active

export class ParentUiComponent {
  active?: UiElementBlock;

  blocks = [
    'ui1',
    'ui2',
    'ui3'
  ];
}

If you are not using the *ngFor , and you are manually placing these blocks, you also have the choice to manually assign a variable to it:如果您不使用*ngFor并且手动放置这些块,您还可以选择手动为其分配变量:

<app-ui-element-block
  [class.active]="block1 === active"
  (click)="active = block1"
  #block1>
</app-ui-element-block>

<div> Some random content </div>

<app-ui-element-block
  [class.active]="block2 === active"
  (click)="active = block2"
  #block2>
</app-ui-element-block>

Things get more wild if these components are spread across multiple parent components.如果这些组件分布在多个父组件中,事情会变得更加疯狂。 You would need to do this logic inside the block itself, in combination with a service:您需要结合服务在块本身内部执行此逻辑:

export interface ActivatableBlock {
  active: boolean;
}

@Injectable({
  providedIn: 'root'
})
export class UiElementBlockService {
  private active?: ActivatableBlock;

  activate(block: ActivatableBlock): void {
    if (this.active) {
      this.active = false;
    }

    block.active = true;
    this.active = block;
  }
}

@Component({
  selector: 'app-ui-element-block',
  template: ``
})
export class UiElementBlock implements ActivatableBlock {
  @HostBinding('class.active')
  active?: boolean;

  constructor(private ub: UiElementBlockService) {}

  @HostListener('click')
  onClick(): void {
    this.ub.activate(this);
  }
}

So, that's just a couple of ways of doing it, without using the DOM, and making things more reusable and easier to test.所以,这只是做这件事的几种方法,不使用 DOM,并使事情更可重用和更容易测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM