My doubts
HostBinding and HostListener are two decorators that you’ve encountered while learning Angular. When I read the API description of these two decorators on the official website, I was really puzzled. Obviously I could understand every word, but I just couldn’t understand them together. And the examples on the official website are also very confusing, which makes me confused about the use scenarios of these two apis.
Website shows
Take a look at the description of these two apis on the website:
HostBinding (link to official website) :
Use to mark a DOM property as a property bound to the host and provide configuration metadata. Angular automatically checks the host property binding during change detection, and if the binding changes, it updates the directive’s host element.
HostListener (official website link) :
Used to declare the DOM event to listen for and to provide the handler method to run when that event occurs.
Did you not know after watching these two brothers use scenes exactly what? In my opinion, the purpose of these two decorators is to simplify the code by extracting a complex DOM operation into a single instruction. No more nonsense, on the code, a look to understand.
Code sample
Let’s say we have a business scenario where we have an input box. Each time we type, the color of the words and the color of the border change. Let’s call it “Rainbow input box”.
If we do not use component encapsulation, we write the relevant DOM operations in the component, as follows:
@Component({
selector: 'app-rainbow-input-demo'.template: ' This is a rainbow input box, < span style =" box-sizing: border-box! Important; word-wrap: break-word! Important; word-wrap: break-word! Important;
.styles: [`.my-input { border:none; outline: none; border: 2px solid #333333; border-radius: 5px; } `]})export class RainbowInputDemoComponent {
// The default color style
public inputStyleObj = {
color:null.borderColor:null};/ library/color
public possibleColors = [
'darksalmon'.'hotpink'.'lightskyblue'.'goldenrod'.'peachpuff'.'mediumspringgreen'.'cornflowerblue'.'blanchedalmond'.'lightslategrey'
];
// Keyboard drop event
onKeyDown(){
const index = Math.floor(Math.random() * this.possibleColors.length);
// If we use this.inputStyleobj. color = this.possiblecolors [index],
//this.inputStyleObj Although the content has changed, because it is a reference type, its address value has not changed. So a re-rendering of the view will not be triggered
// In Angular, as with React, modifying a reference type directly does not trigger a rerender. Only overwriting it or merging it so that its address value changes will trigger a rerender
// If that's too much trouble, you can always use [style.color] and [style.borderColor] in the template.
this.inputStyleObj = {
color:this.possibleColors[index],
borderColor:this.possibleColors[index],
}
}
}
Copy the code
The effect is as follows:
So, we’ve implemented this, and now we have a problem. What if we need this rainbowInput for other components? Do we have to copy and paste the code every time we use it? Obviously this is not the principle of component packaging, and if you do this, the technical manager or project manager will blow your head off.
Then we need to encapsulate it as a component or a directive. In this article, we’ll wrap it up as an instruction, and we’ll see why later. The code is as follows:
@Directive({
selector: '[appRainbow]'
})
export class RainbowInputDirective {
public possibleColors = [
'darksalmon'.'hotpink'.'lightskyblue'.'goldenrod'.'peachpuff'.'mediumspringgreen'.'cornflowerblue'.'blanchedalmond'.'lightslategrey'
];
// Font color
@HostBinding('style.color') color: string;
// Border color
@HostBinding('style.borderColor') borderColor: string;
// Listen for keyboard dropped events
@HostListener('keydown') onKeyDown() {
// Get a random color
const index = Math.floor(Math.random() * this.possibleColors.length);
this.color = this.borderColor = this.possibleColors[index]; }}@Component({
selector: 'app-rainbow-input-demo'.template: .styles: [// Omit, same as above]})export class RainbowInputDemoComponent {}
Copy the code
As shown in the above code, we have extracted the repetitive logic, making the code much more maintainable and aesthetically pleasing.
conclusion
In the code we can see that @hostBinding actually binds a property to the host element, but it’s not just a random property. This property refers to the property supported by Angular templates. @hostbinding is equivalent to [] or bind- in the template. Similarly @hostListener is equivalent to () or on- in the template. This allows us to bind attributes and methods to host elements in directives, just as we did when we wrote (keydow) and [style] directly to the template. So, you can’t just write strings in these decorators.
About directives and components
In Angular, however, there is not much difference between a Component and a Directive because the angular Component decorator @Component is inherited from @Directive.
In fact, we can encapsulate the DOM operation into a component, as follows
@Component({
selector:'input[appRainbow]'
})
Copy the code
But with instructions:
@Directive({
selector: '[appRainbow]'
})
Copy the code
It really doesn’t make much difference.
conclusion
@hostbinding is equivalent to [] or bind- on the template;
@hostListener is equivalent to () or on- in the template;
The data and method bindings in directives that Angular provides to keep us from directly manipulating the DOM.
The resources
Angular @hostbinding () and @hostListener () usage