Angular 5 - Внедрение поставщика услуг во все компоненты с удлинителями - PullRequest
0 голосов
/ 09 мая 2018

Я немного знаком с Angular и пытаюсь построить свое приложение на нем, но у меня возникают некоторые проблемы при добавлении служб в мои Компоненты.

Я добавил сторонний модуль с поставщиком услуг для переводов на несколько языков на лету, так как это довольно сложно сделать вручную, и поставщиком услуг cookie. Основная проблема заключается в том, что перевод выполняется во время компиляции шаблона, поэтому для достижения этого для моего компонента я должен использовать код, подобный следующему:

<!-- language: typescript -->
import { Component, OnInit } from '@angular/core';

import { TranslateService } from '@ngx-translate/core';
import { CookieService } from 'ngx-cookie-service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

  language: string;

  constructor(
    private translateService: TranslateService,
    private cookieService: CookieService) { }

  ngOnInit() {
    this.language = this.cookieService.get('lang') || 'en';
    this.translator.use(this.language);
  }

}

Основная проблема заключается в том, что мне приходится каждый раз передавать этим поставщикам услуг функцию конструктора в каждом компоненте, что очень повторяется. Чтобы предотвратить это, я попытался создать abstract class, а затем расширить его в своих компонентах в качестве базового компонента. Примерно так:

<!-- language: typescript -->

import { Injectable, OnInit } from '@angular/core';

import { TranslateService } from '@ngx-translate/core';
import { CookieService } from 'ngx-cookie-service';

@Injectable()
export abstract class DefaultComponent implements OnInit {

  language: string;

  constructor(private translator: TranslateService, private cookieService: CookieService) {
    this.language = this.cookieService.get('lang') || 'es';
    this.translator.use(this.language);
  }

  ngOnInit() {
    // 
  }

}

<!-- language: typescript -->
import { Component } from '@angular/core';

import { DefaultComponent } from '../default.component';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent extends DefaultComponent {

  ngOnInit() {
    // Everything here replaces the ngOnInit from parent
  }

}

Это решение работает для многих моих компонентов, но у меня есть один компонент с именем PostsComponent, который использует определенного поставщика услуг для обработки Posts. Это код:

<!-- language: typescript -->
import { Component } from '@angular/core';

import { DefaultComponent } from '../default.component';

import { Post } from '../../models/post';
import { PostService } from '../../services/post/post.service';

@Component({
  selector: 'app-posts',
  templateUrl: './posts.component.html',
  styleUrls: ['./posts.component.css'],
  providers: [ PostService ]
})
export class PostsComponent extends DefaultComponent {

  posts: Post[];

  constructor(private postService: PostService) { }

  ngOnInit() {
    this.getPosts();
  }

  getPosts(): void {
    this.postService.getPosts().subscribe(posts => this.posts = posts);
  }

}

Если я использую функцию конструктора для этого компонента, чтобы использовать поставщика услуг, родительский конструктор переопределяется. Чтобы предотвратить это, я должен вызвать функцию super() в функции конструктора, но мне нужно будет отправить TranslateService и CookieService этой функции, чтобы она все работала. Как я сказал в начале, это повторяется, и мне это не очень нравится.

Как мне добиться загрузки этих общих служб для каждого компонента и при этом разрешить использовать конкретные службы для конкретных компонентов? Я не думаю, что установка этих общих служб в качестве глобальных переменных является хорошей практикой. Поправь меня, если я ошибаюсь.

Спасибо за ваше время.

1 Ответ

0 голосов
/ 09 мая 2018

Чтобы дочерний класс имел дополнительные зависимости, он должен также перечислить родительские зависимости и передать их в super:

export class PostsComponent extends DefaultComponent {
  ...
  constructor(
    translator: TranslateService,
    cookieService: CookieService,
    private postService: PostService
  ) {
    super(translator, cookieService);
  }
  ...
}

Родительские зависимости не должны иметь модификатора видимости, поскольку они уже назначеныэкземпляр в родительском конструкторе.

Если имеется много зависимостей, родительский класс может быть реорганизован для использования Injector в конструкторе для их получения, Injector будет единственной зависимостью, которую необходимо передать super.Если существует вероятность того, что список родительских зависимостей будет расширен в будущем, может быть разумно использовать Injector сразу.

Другого хорошего пути решения проблемы нет.Этот шаблонный код является ценой для беспроблемного опыта Angular.Любой другой способ в настоящее время может считаться хаком.

Всегда существует вероятность того, что список родительских зависимостей слишком велик.В этом случае всегда будет шаблонный код, потому что компонент должен содержать бизнес-логику для переключения языков, а его роль - это логика представления (обратите внимание, что выбор языка в ngOnInit делает невозможным переключение языков без перекомпиляции дерева компонентов, что является потенциальным проектомнедостаток).Предпочтительно объединить TranslateService и CookieService в пользовательскую службу, которая будет отвечать за переключение языков.Это приложение композиция по принципу наследования .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...