@HostBinding e @HostListener: o que eles fazem e para que servem?

188

Nos meus meandros pela interweb mundial, e agora especialmente nos documentos do estilo angular.io , encontro muitas referências a @HostBindinge @HostListener. Parece que são fundamentais, mas infelizmente a documentação para eles no momento é um pouco superficial.

Alguém pode explicar o que são, como eles funcionam e dar um exemplo de seu uso?

serlingpa
fonte

Respostas:

139

Você verificou esses documentos oficiais?

HostListener - Declara um ouvinte de host. Angular invocará o método decorado quando o elemento host emitir o evento especificado.

@HostListener- escutará o evento emitido pelo elemento host declarado com @HostListener.

HostBinding - Declara uma ligação de propriedade do host. O Angular verifica automaticamente as ligações das propriedades do host durante a detecção de alterações. Se uma ligação mudar, ele atualizará o elemento host da diretiva.

@HostBinding- vinculará a propriedade ao elemento host. Se uma ligação mudar, HostBindingatualizará o elemento host.


NOTA: Ambos os links foram removidos recentemente. A parte " HostBinding-HostListening " do guia de estilo pode ser uma alternativa útil até o retorno dos links.


Aqui está um exemplo de código simples para ajudar a imaginar o que isso significa:

DEMO: Aqui está a demonstração ao vivo no plunker - "Um exemplo simples sobre @HostListener e @HostBinding"

  • Este exemplo liga uma rolepropriedade - declarada com @HostBinding- ao elemento do host
    • Lembre-se de que roleé um atributo, pois estamos usando attr.role.
    • <p myDir>torna-se <p mydir="" role="admin">quando você o visualiza nas ferramentas do desenvolvedor.
  • Ele escuta o onClickevento declarado com @HostListener, anexado ao elemento host do componente, mudando rolea cada clique.
    • A alteração quando o <p myDir>botão é clicado é que sua tag de abertura muda de um lado <p mydir="" role="admin">para o outro <p mydir="" role="guest">.

directives.ts

import {Component,HostListener,Directive,HostBinding,Input} from '@angular/core';

@Directive({selector: '[myDir]'})
export class HostDirective {
  @HostBinding('attr.role') role = 'admin'; 
  @HostListener('click') onClick() {
    this.role= this.role === 'admin' ? 'guest' : 'admin';
  }
}

AppComponent.ts

import { Component,ElementRef,ViewChild } from '@angular/core';
import {HostDirective} from './directives';

@Component({
selector: 'my-app',
template:
  `
  <p myDir>Host Element 
    <br><br>

    We have a (HostListener) listening to this host's <b>click event</b> declared with @HostListener

    <br><br>

    And we have a (HostBinding) binding <b>the role property</b> to host element declared with @HostBinding 
    and checking host's property binding updates.

    If any property change is found I will update it.
  </p>

  <div>View this change in the DOM of the host element by opening developer tools,
    clicking the host element in the UI. 

    The role attribute's changes will be visible in the DOM.</div> 
    `,
  directives: [HostDirective]
})
export class AppComponent {}
micronyks
fonte
1
são este decorador usado ainda parece que os links foram removidos do angular2 documentação
CommonSenseCode
1
Sim, ele ainda está em uso, mas deixe-me confirmar uma vez. Vou atualizá-lo, se eu conseguir descobrir outra coisa.
micronyks
Eles estão no cheat sheet: angular.io/docs/ts/latest/guide/cheatsheet.html
Targaryen
1
@ Mr.EasyAnswersMcFly resposta atualizada com nota e link. Observe que ainda a documentação adequada não está disponível.
micronyks
1
@MuhammadSaleh para rolagem é difícil dizer que a forma como ele conta e calcula ... mas isso é para garantir que cada instância terá um ouvinte separado
micronyks
112

Uma dica rápida que me ajuda a lembrar o que eles fazem -

HostBinding('value') myValue; é exatamente o mesmo que [value]="myValue"

E

HostListener('click') myClick(){ } é exatamente o mesmo que (click)="myClick()"


HostBindinge HostListenersão escritos em diretivas e nas outras (...)e [..]são escritos dentro de modelos (de componentes).

Shai Reznik - HiRez.io
fonte
9
Ah, clicou (trocadilhos) comigo, graças a esta resposta. @HostListeneré o caminho a percorrer quando você não tem nada no DOM para a ligação típica de eventos, como entrada de teclado no meu caso.
MrBoJangles
47

Aqui está um exemplo básico de foco instantâneo.

Propriedade de modelo do componente:

Modelo

<!-- attention, we have the c_highlight class -->
<!-- c_highlight is the selector property value of the directive -->

<p class="c_highlight">
    Some text.
</p>

E nossa diretiva

import {Component,HostListener,Directive,HostBinding} from '@angular/core';

@Directive({
    // this directive will work only if the DOM el has the c_highlight class
    selector: '.c_highlight'
 })
export class HostDirective {

  // we could pass lots of thing to the HostBinding function. 
  // like class.valid or attr.required etc.

  @HostBinding('style.backgroundColor') c_colorrr = "red"; 

  @HostListener('mouseenter') c_onEnterrr() {
   this.c_colorrr= "blue" ;
  }

  @HostListener('mouseleave') c_onLeaveee() {
   this.c_colorrr = "yellow" ;
  } 
}
serkan
fonte
28
Não vejo essa resposta aceita como resposta à pergunta. Você gostaria de fornecer alguma explicação? Como o que c_colorrr, c_onEnterrr (), c_onLeaveeee fazem nesse snippet de código específico?
luqo33 5/05
1
Acho que deve mudar de cor no evento de entrada do mouse para azul e no evento de saída do mouse para amarelo.
Michał Ziobro
Onde você coloca a diretiva na marcação? Parece que você o colocaria na tag body, mas isso estaria fora do componente raiz. Se você está confuso com a esta resposta neste link pode ajudar ng2.codecraft.tv/custom-directives/hostlistener-and-hostbinding
mtpultz
@mtpultz Está na classe.
serkan
33

Outra coisa interessante @HostBindingé que você pode combiná-lo com @Inputse sua ligação depende diretamente de uma entrada, por exemplo:

@HostBinding('class.fixed-thing')
@Input()
fixed: boolean;
Altschuler
fonte
1
Você pode compartilhar exemplo de uso com @Input()?
Mano
O exemplo está logo ali na minha resposta, você simplesmente escrever ambos os decoradores um após o outro, a ordem deve ser irrelevante
Altschuler
1
Eu acho que o que está faltando é como isso difere de apenas usar @HostBinding. Quando você precisa usar @Input?
1252748
11

Uma coisa que acrescenta confusão a esse assunto é que a ideia de decoradores não fica muito clara, e quando consideramos algo como ...

@HostBinding('attr.something') 
get something() { 
    return this.somethingElse; 
 }

Funciona porque é um getacessador . Você não poderia usar uma função equivalente:

@HostBinding('attr.something') 
something() { 
    return this.somethingElse; 
 }

Caso contrário, o benefício do uso @HostBindingé que ele garante que a detecção de alterações seja executada quando o valor limite for alterado.

Feito
fonte
9

Resumo:

  • @HostBinding: Este decorador vincula uma propriedade de classe a uma propriedade do elemento host.
  • @HostListener: Este decorador vincula um método de classe a um evento do elemento host.

Exemplo:

import { Component, HostListener, HostBinding } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `<p>This is nice text<p>`,
})
export class AppComponent  {

  @HostBinding('style.color') color; 

  @HostListener('click')
  onclick() {
    this.color =  'blue';
  }

}

No exemplo acima, ocorre o seguinte:

  • Um ouvinte de evento é adicionado ao evento de clique, que será acionado quando um evento de clique ocorrer em qualquer lugar do componente
  • A colorpropriedade em nossa AppComponentclasse está vinculada à style.colorpropriedade no componente. Assim, sempre que a colorpropriedade for atualizada, também a style.colorpropriedade do nosso componente
  • O resultado será que sempre que alguém clicar no componente, a cor será atualizada.

Uso em @Directive:

Embora possa ser usado no componente, esses decoradores são frequentemente usados ​​em diretivas de atributo. Quando usado em um @Directivehost, altera o elemento no qual a diretiva é colocada. Por exemplo, dê uma olhada neste modelo de componente:

<p p_Dir>some paragraph</p>

Aqui p_Dir é uma diretiva sobre o <p>elemento Quando @HostBindingou @HostListeneré usado dentro da classe de diretiva, o host agora se refere ao <p>.

Willem van der Veen
fonte
6

Teoria com menos jargões

O @Hostlistnening lida basicamente com o elemento host, digamos (um botão), ouvindo uma ação do usuário e executando uma determinada função, digamos alerta ("Ahoy!"), Enquanto o @Hostbinding é o contrário. Aqui, ouvimos as alterações que ocorreram nesse botão internamente (digamos quando foi clicado no que aconteceu com a classe) e usamos essa alteração para fazer outra coisa, digamos, emitir uma cor específica.

Exemplo

Pense no cenário em que você gostaria de criar um ícone favorito em um componente. Agora você sabe que precisaria saber se o item foi Favoritado com sua classe alterada. Precisamos de uma maneira de determinar isso. É exatamente aí que o @Hostbinding entra.

E onde há a necessidade de saber qual ação realmente foi executada pelo usuário, é onde o @Hostlistening entra

Ralphkay
fonte
3
Isso é confuso e os nomes dos decoradores são imprecisos.
Matmancini 02/02/19