Use @HostBindings instead host in angular 4

2020-05-27 09:33发布

问题:

I just try to make animation with angular 4 and I saw tutorial that use host in the component

import { Component, OnInit, HostBinding } from '@angular/core';
import { AngularFire, AuthProviders, AuthMethods } from 'angularfire2';
import { Router } from '@angular/router';
 import { moveIn } from '../router.animations';

@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css'],
animations: [moveIn()],
host: {'[@moveIn]': ''}
})

but it shows me error under the host property "[tslint] use @hostBindings and @HostListeners instead of the host property"

回答1:

tslint are not errors. They are TypeScript linting messages created by the tslint webpack service.

You can read more on TSLint here:

https://palantir.github.io/tslint/

For some reason, someone decided that using the host property in a component was a bad practice. You're perfectly fine to use that feature, and the other component configuration features.

To disable this lint check edit your tslint.json file and add/modify the following:

    "use-host-property-decorator": false

Setting it to false disables the check.



回答2:

For those who come across this in the future, I'd like to shed some light on why its a linting error, and why or why not you should use the host property.

So, there are a couple ways to set properties and listen to events on the host component. The host property in the component decorator or with @HostBinding (for properties) and @HostListener (for events).

When we use the host property, we can use syntax that's exactly like it is in templates, [] and () and direct properties like class. This is great because you don't have to import anything and when you look at it, you'll pretty much know what will happen. Now, when you get into some more complex scenarios, like setting aria properties your logic in these properties get complicated. E.g:

@Component({
   selector: 'my-component',
   host: {
     '[attr.aria-expanded]': 'expanded'
   }
})
export class MyComponent {
   expanded: boolean = false
}

Here we can see that the expanded property is used to set the aria-expanded attribute on the host. Using any tooling, whether it be IDE's, TypeScript, LanguageExtensions, we would not be able to see the two are linked.

This causes a problem when you do refactoring, and you missed the logic that are in those strings. And when that happens, it's a real pain.

So to get around that, you would use the @HostBinding decorator.

@Component({
   selector: 'my-component'
})
export class MyComponent {
   @HostBinding('attr.aria-expanded')
   expanded: boolean = false
}

Now you can change the name of the property to what ever you want and everyone is happy.


That is until you get to properties that could affect multiple host element attributes, or that actually has some kind of logic to it.

HostBinding

@Component({
   selector: 'my-component'
})
export class MyComponent {
   @HostBinding('attr.aria-expanded')
   @HostBinding('class.expanded')
   expanded: boolean = false
}

Some people don't like the multiple @HostBindings on a property. And that could be changed to:

host

@Component({
   selector: 'my-component',
   host: {
      '[attr.aria-expanded]': 'expanded',
      '[class.expanded]': 'expanded',
   }
})
export class MyComponent {
   expanded: boolean = false
}

And properties that actually has logic:

HostBinding

@Component({
   selector: 'my-component'
})
export class MyComponent {
   @HostBinding('attr.aria-expanded')
   @HostBinding('class.expanded')
   get expanded(): boolean {
      // Don't actually do this, this is just an example for Hostbinding vs. host
      return this._expanded ? true : null
   }

   // create a setter here as well.

   private _expanded: boolean = false
}

vs host

@Component({
   selector: 'my-component',
   host: {
      '[attr.aria-expanded]': 'expanded ? true : null',
      '[class.expanded]': 'expanded',
   }
})
export class MyComponent {
   expanded: boolean = false
}

So, now that we know what each does, we can talk about why host properties are flagged by the linter by default.

When using the host properties, there's really no checks to actually see if you spelled the property correctly. When you build Angular with AoT (which is usually for production) you'll most likely get the errors, and then fix it. It's just quicker to get feedback in your editor when using @HostBinding, rather than wait for a long build progress (depending on how big your application is, actually).

So, because of that almost unknown (to today's compilers) string values, using host properties is flagged by default.

Maybe in the future when AoT could be used in development (I think with the Ivy renderer?), we could get those compiler errors. But in the mean time, we're not there yet.



回答3:

@Reactgular post respose:

To disable this lint check edit your tslint.json file and add/modify the following:

"use-host-property-decorator": false

This property is renamed to: no-host-metadata-property so the code in tslint.json is:

"no-host-metadata-property": false