Angular 5-所有扩展组件中的服务提供商注入 [英] Angular 5 - Service provider injection in all components with extends

查看:53
本文介绍了Angular 5-所有扩展组件中的服务提供商注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Angular有点陌生,我试图围绕它构建我的应用程序,但是在向我的组件中注入服务时遇到了一些麻烦.

I'm kinda new with Angular and I'm trying to build my app around it, but I'm having some troubles when injecting services in my Components.

我添加了一个第三方服务模块和一个服务提供商,该服务提供商可以即时进行多种语言的翻译,因为手动操作有点困难",还提供了一个cookie服务提供商.主要问题是翻译是在模板编译期间进行的,因此要实现对我的组件的转换,我必须使用如下代码:

I've added a 3rd party module with a service provider for translations in multiple languages on the fly, as it is kinda "hard" to do it manually, and a cookie service provider. The main problem is that the translation is made during template compilation, so to achieve that for my component I have to use a code like this:

<!-- 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);
  }

}

主要问题是我必须每次在每个组件的构造函数中传递那些服务提供者,这是非常重复的.为了防止这种情况,我尝试创建一个抽象类,然后将其作为基本组件扩展到我的组件中.像这样:

The main problem is that I have to pass those service providers everytime in the constructor function in every component, which is very repetitive. To prevent that, I've tried to create an abstract class then extend it in my components as a base component. Something like this:

<!-- 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 的组件,该组件使用特定的服务提供商来处理 Post .这是代码:

This solution works for many of my components, but I have one component called PostsComponent that uses a specific service provider to handle Posts. This is the code:

<!-- 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 发送给该函数.功能,以使其能够正常工作.正如我在开始时所说的,这是重复性的,我不太喜欢.

If I use the constructor function for that component to use service provider, the parent constructor is overriden. To prevent that, I should call to super() function in the constructor function, but I will have to send the TranslateService and CookieService to that function in order to make it work everything. As I said in the beginning, this is repetitive and I do not like that so much.

如何实现为每个组件加载那些通用服务,同时仍然允许对特定组件使用特定服务?我认为将这些通用服务设置为全局变量不是一个好习惯.如果我错了,请纠正我.

How can I achieve to load those common services for every component and still allowing to use specific services for specific components? I don't think setting up those common services as global variables is a good practice. Correct me if I'm wrong.

感谢您的时间.

推荐答案

为使子类具有其他依赖项,它还应列出父项的依赖项并将其传递给 super :

In order for child class to have additional dependencies, it should list parent's dependencies as well and pass them to super:

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

父级的依赖项应该没有可见性修饰符,因为它们已经在父级构造函数中分配给实例了.

Parent's dependencies should have no visibility modifier because they are already assigned to instance in parent constructor.

如果存在许多依赖关系,则可以将父类重构为在构造函数中使用 Injector 来获取它们, Injector 将是唯一需要传递给的依赖项 super .如果将来有可能扩展父级依赖项列表,则可以立即使用 Injector .

In case there are many dependencies, parent class can be refactored to use Injector in constructor to get them, Injector will be the only dependency that needs to be passed to super. If there is a possibility that list of parent's dependencies will be extended in future, it may be reasonable to use Injector right away.

没有其他好的方法.此样板代码是无故障Angular体验的价格.目前可以将任何其他方式视为黑客行为.

There is no other good way around. This boilerplate code is the price for trouble-free Angular experience. Any other way can currently be considered a hack.

始终有一个父级依赖项列表太大的机会.在这种情况下,总会有样板代码,因为一个组件应该包含用于切换语言的业务逻辑,而它的作用是表示逻辑(请注意, ngOnInit 中的语言选择使得不重新编译组件树就无法切换语言,这是潜在的设计缺陷).最好将 TranslateService CookieService 合并到负责切换语言的自定义服务中.这是基于继承的组合原理的应用.

There is always a chance that a list of parent dependencies is too big. In this case there will always be boilerplate code because a component should contain business logic for switching languages, while it's role is presentation logic (notice that language choice in ngOnInit makes it impossible to switch languages without component tree recompilation, which is potential design flaw). It is preferable to merge TranslateService and CookieService into custom service that will be responsible for switching languages. This is an application of composition over inheritance principle.

这篇关于Angular 5-所有扩展组件中的服务提供商注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆