Właściwość „X” jest prywatna i dostępna tylko w klasie „xyzComponent”


102

Próbuję zbudować aplikację angular2 do produkcji, śledzę tego bloga . Po udanej kompilacji ngc, gdy ma miejsce kompilacja tsc , generuje poniższy błąd pokazany na obrazku:

wprowadź opis obrazu tutaj

Po dłuższych poszukiwaniach znalazłem tego bloga, który wyjaśnia problem w sekcji „Właściwość kontekstu”, którego nie jestem w stanie poprawnie zrozumieć, może to dobry pomysł, że to co się dzieje nie tak. w zasadzie kiedy ustawiamy zmienną jako prywatną, otrzymujemy "BŁĄD: Właściwość jest prywatna i dostępna tylko w klasie" . Nie rozumiem, dlaczego to nadchodzi.

Prosimy o pomoc, bo przez ostatnie kilka dni waliliśmy się w głowę z tym problemem.


1
czy próbowałeś zmienić właściwość z prywatnej na publiczną?
Xin Meng

czy możesz udostępnić zawartość pliku ts, która powoduje błąd?
Raj

Odpowiedzi:


143

Dla danego składnika wszystkie jego elementy członkowskie (metody, właściwości), do których ma dostęp jego szablon, muszą być publiczne w scenariuszu kompilacji AOT. Wynika to z faktu, że szablon jest przekształcany w klasę TS. Wygenerowana klasa i komponent są teraz dwiema oddzielnymi klasami i nie możesz uzyskać dostępu do prywatnych elementów członkowskich między klasami.

Krótko mówiąc: nie możesz uzyskać dostępu do prywatnych członków w swoich szablonach, jeśli chcesz użyć kompilacji z wyprzedzeniem.

Dla lepszego wyjaśnienia https://github.com/angular/angular/issues/11422


ale tak nie było we wcześniejszych wersjach Angulara, prawda? Zacząłem otrzymywać te błędy po aktualizacji do najnowszej wersji.
Emil

37

Być może inną, jeszcze prostszą odpowiedzią jest:

Chłopaki, nie wywołujcie prywatnych metod, pól ani właściwości z HTML :)


PS podczas kompilowania *.tskodu do *.js, AOT odmawia połączenia niepublicznych członków z szablonem HTML .

I "tak", to spowoduje, że potok kompilacji zawiedzie: D


1
Lub uzyskaj dostęp do prywatnych pól / właściwości!
JMK

@Arsen Khachaturyan To zabawne)
voodoo417

@JMK Zaktualizowałem post zgodnie z twoją sugestią, dziękuję.
Arsen Khachaturyan

@ voodoo417, zabawne i prawdziwe;). Czasami zbyt akademicka odpowiedź może naprawdę zaskoczyć każdego i po prostu musimy być tak prostsi, jak to tylko możliwe.
Arsen Khachaturyan

1
@Arsen Khachaturyan Zgadzam się, Arsen +++
voodoo417

17

Otrzymałem to, gdy zadeklarowałem prywatne iniekcje w konstruktorze:

constructor(private service: SpecificObjectService) { }

I użyłem ich w szablonie:

*ngFor="let pd of service.listSpecificObject "

Rozwiązaniem jest:

constructor(public service: SpecificObjectService) { }

16

Więc naprawiłem ten problem, pozostawiam to krótkie i proste. Aby to naprawić, głęboko przeczytałem tego bloga . Jak w sekcji „ Właściwość kontekstu ” Rozwiązanie tego problemu polega na tym, że nie używaj ani nie twórz zmiennej prywatnej, jeśli chcesz jej używać bezpośrednio w widoku podczas tworzenia kompilacji z AOT ( tj. Ahead Of Time ) dla produkcja.

*na przykład *

// component.ts
@Component({
  selector: 'third-party',
  template: `
    {{ _initials }}
  `
})
class ThirdPartyComponent {
  private _initials: string;
  private _name: string;

  @Input()
  set name(name: string) {
    if (name) {
      this._initials = name.split(' ').map(n => n[0]).join('. ') + '.';
      this._name = name;
    }
  }
}

dane wyjściowe: Właściwość „_initials” jest prywatna i dostępna tylko w klasie „ThirdPartyComponent”.

Rozwiązanie:

zaktualizuj to private _initials: string;po prostu_initials: string;

W tej odpowiedzi Harish Gadiya zapewni mi pomoc, a dzięki temu.


nie trzeba go _nametam używać , może być taki sam, jak używany, this.a inna namejego zmienna lokalnathis.name=name;
LazerBanana.

@LazerBanana, ale this.name=namew set namejest inf. rekurencja
vp_arth

@vp_arth? jeden jest lokalny, jeden jest globalny? nawet z tą samą nazwą 2 różne rzeczy, jak sądzę? dlatego this.
zwykłeś

Co masz na myśli, mówiąc lokalnie / globalnie? namenie jest zmienną, jest własnością obiektu. this.name = namewywoła setter ( set name(v){}) na tym obiekcie. Tak łatwo to przetestować: blitz Maximum call stack size exceeded
vp_arth

6

Dla mnie to działa: po prostu zmień usługę na publiczną.

constructor(public service: SpecificObjectService) { }

Aplikacja działa w produkcji !!


Czyli dokładnie to samo rozwiązanie z mniej szczegółową odpowiedzią, jak odpowiedź @ TiyebM powyżej.
Ash

1

ok zobacz, to naprawdę prosty problem z javascriptem es6, jeśli musisz zachować prywatność typu danych, możesz po prostu to zrobić

privateAccess(){
     return this.cannotAccessByInstanceButStillNeeded
}

0

Jeśli chcesz używać routera w widoku, upublicznij go.

Na przykład:

<button 
   [routerLink]="['/login']"
   [queryParams]="{redirectTo: router.url}"
   translate="Please sign in to use this feature"
/>
import { Router } from '@angular/router'; 

constructor(
   public router: Router; // don't make it private
) {}

Przeoczyłem to, dopóki Github CI nie wyśle ​​mi ostrzeżenia.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.