代码之家  ›  专栏  ›  技术社区  ›  AndreaNobili

在这个Angular 2应用程序中,这种跨组件通信“模式”究竟是如何工作的?

  •  1
  • AndreaNobili  · 技术社区  · 7 年前

    我是个新手 角度2

    在我的应用程序中,我有这个 配方服务 服务等级:

    @Injectable()
    export class RecipeService {
    
      // Hold a Recipe object to be emitted to another component to implement cross component comunication:
      recipeSelected = new EventEmitter<Recipe>();
    
      // List of all recipes (maybe later can be obtained by a web service)
      private recipes: Recipe[] = [
        new Recipe(
          'Tasty Schnitzel',
          'A super-tasty Schnitzel - just awesome!',
          'https://upload.wikimedia.org/wikipedia/commons/7/72/Schnitzel.JPG',
          [
            new Ingredient('Meat', 1),
            new Ingredient('French Fries', 20)
          ]),
        new Recipe('Big Fat Burger',
          'What else you need to say?',
          'https://upload.wikimedia.org/wikipedia/commons/b/be/Burger_King_Angus_Bacon_%26_Cheese_Steak_Burger.jpg',
          [
            new Ingredient('Buns', 2),
            new Ingredient('Meat', 1)
          ])
      ];
    
      // Inject a sub service:
      constructor(private slService: ShoppingListService) {}
    
      /**
       * Return a copy of the reipes array.
       * @returns {Recipe[]}
       */
      getRecipes() {
        return this.recipes.slice();
      }
    
      addIngredientsToShoppingList(ingredients: Ingredient[]) {
        this.slService.addIngredients(ingredients);
      }
    }
    

    该类由两个不同的组件使用,以实现该发射器的跨组件通信:

    recipeSelected = new EventEmitter<Recipe>();
    

    根据我的理解(如果我做了错误的断言,请纠正我),这 当选食谱 配方 对象(它包含一些字符串字段)。

    然后我有这个 组件(它代表一个配方,视图显示与特定配方相关的信息):

    @Component({
      selector: 'app-recipe-item',
      templateUrl: './recipe-item.component.html',
      styleUrls: ['./recipe-item.component.css']
    })
    export class RecipeItemComponent implements OnInit {
      @Input() recipe: Recipe;
    
      // Inkect the RecipeService to use it in this component:
      constructor(private recipeService: RecipeService) { }
    
      ngOnInit() {
      }
    
      /**
       * When a specific recipe is selected in the page it emit the selected recipe to comunicate
       * with another component
       */
      onSelected() {
        this.recipeService.recipeSelected.emit(this.recipe);
      }
    
    }
    

    当用户点击链接进入与此相关的视图时 执行此类的方法。

    射击 对于其他人来说,这个对象的内容,其中其他人应该是另一个组件(因此它实现了跨组件通信的概念)。

    然后我有另一个 配方组件

    @Component({
      selector: 'app-recipes',
      templateUrl: './recipes.component.html',
      styleUrls: ['./recipes.component.css'],
      providers: [RecipeService]
    })
    export class RecipesComponent implements OnInit {
      selectedRecipe: Recipe;
    
      /**
       * Inject the RecupeService to use it in this component
       * @param recipeService
       */
      constructor(private recipeService: RecipeService) { }
    
      /**
       * Subscribe on the event emitted when a recipe is selected:
       */
      ngOnInit() {
        this.recipeService.recipeSelected
          .subscribe(
            (recipe: Recipe) => {
              this.selectedRecipe = recipe;
            }
          );
      }
    
    }
    

    据我所知,我正在注册“监听器”(它是监听器吗?)对于此类事件 ngOnInit()

      ngOnInit() {
        this.recipeService.recipeSelected
          .subscribe(
            (recipe: Recipe) => {
              this.selectedRecipe = recipe;
            }
          );
      }
    

    组件发出包含 配方 对象,该信息由 配方组件 使用它的组件。它是?

    (recipe: Recipe) => {
        this.selectedRecipe = recipe;
    }
    

    配方:配方

    另一个疑问是:为什么将此代码声明为 ? 我的想法是,当这个组件被创建时,它声明一个监听器,然后这个监听器对可能再次出现的事件做出反应。它是?

    2 回复  |  直到 7 年前
        1
  •  2
  •   DeborahK    7 年前

    EventEmitter 在服务中使用。

    请参阅此帖子: What is the proper use of an EventEmitter?

    Use by directives and components to emit custom Events.
    

    不用于服务。正如@Pablo所提到的,即使对于组件,也建议您使用@Output来公开事件。

    https://blogs.msmvps.com/deborahk/build-a-simple-angular-service-to-share-data/

    这里有一个对应的Plunk: https://plnkr.co/edit/KT4JLmpcwGBM2xdZQeI9?p=preview

    import { Injectable } from '@angular/core';
    
    @Injectable() 
    export class DataService {
      serviceData: string; 
    }
    

    因此:

    @Injectable()
    export class RecipeService {
    
      recipeSelected = new EventEmitter<Recipe>();
    

    变成这样:

    @Injectable()
    export class RecipeService {
    
      recipeSelected: Recipe;
    

      onSelected() {
        this.recipeService.recipeSelected.emit(this.recipe);
      }
    

    变成这样:

      onSelected() {
        this.recipeService.recipeSelected=this.recipe;
      }
    

    export class RecipesComponent implements OnInit {
      selectedRecipe: Recipe;
    
      ngOnInit() {
        this.recipeService.recipeSelected
          .subscribe(
            (recipe: Recipe) => {
              this.selectedRecipe = recipe;
            }
          );
      }
    
    }
    

    export class RecipesComponent implements OnInit {
      get selectedRecipe(): Recipe {
         return this.recipeService.recipeSelected;
      };   
    }
    

    每次 recipeSelected 更改时,将通知角度变化检测,UI将重新绑定到的当前值 selectedRecipe .

        2
  •  1
  •   Pablo Lozano    7 年前

    @Output 属性,但无论如何,您的分析是正确的。

    MDN documentation

    ngOnInit() :通常在Angular中,构造函数仅用于注入依赖项,因为主初始化逻辑是在 ngOnInit @Input