【问题标题】:Angular 6 - How to process all Components together? Not individuallyAngular 6 - 如何一起处理所有组件?不是单独的
【发布时间】:2018-11-16 09:22:49
【问题描述】:

我的网站需要发布广告。我从 AdServer 收到的广告。我目前有一个组件来完成这项工作。它的工作原理是这样的:

<div>
  ...
  <app-advertising adPos="x22"></app-advertising>
  ...
  <app-advertising adPos="Top"></app-advertising>
  ...
  <app-advertising adPos="x94"></app-advertising>
  ...
</div>

目前在我的 Angular v6 组件中我需要单独处理每个标签。这意味着(在本例中)对 AdServer 的 3 个不同请求。

但我们的 AdServer 也支持 1 个连接所有 adPos 的请求。但要做到这一点,我需要阅读所有组件标签并对所有组件发出 1 个请求。如何使用 Angular 2+ 来做到这一点?

【问题讨论】:

  • 您能否添加更多代码来说明您目前如何提交广告请求?
  • @chau-tran 请在下面查看我自己的答案。

标签: angular angular2-services angular-components angular2-components angular6


【解决方案1】:

将您的广告放在一个数组中然后循环。

类似这样的:

<app-advertising *ngFor="let ad of ads"
[adPos]="ad">
</app-advertising>

【讨论】:

  • 问题是组件标签&lt;app-advertising&gt;位于不同的模板/位置。这不是顺序的。
【解决方案2】:

我认为您将不得不重写您的代码。每个应用程序广告是否都向 AdServer 发出请求? 如果是这样,您可以创建一个接收数组并查询 AdServer 的服务(pseucod-pseudo-code):

class YourService {

   queryAdserver(arrayOfIds): Observable<Array> {
     // query the AdServerService
   }
}

你的父组件使用这个服务

adServerData: any/ // I don't know the Type here, so I set any
constructor(yourService: YourService) {}

ngOnInit() {
   this.yourService.queryAdserver(['x22', 'Top', 'x94'])
   .subscribe( data => {
      this.adServerData = data;
   })
}

模板使用此数据并传递数据,而不是 id

<app-advertising [data]="adServerData[0]"></app-advertising>
...
<app-advertising [data]="adServerData[1]"></app-advertising>
...
<app-advertising [data]="adServerData[2]"></app-advertising>

请注意,这是某种伪代码,解释了如何只查询一次此 AdServer 服务然后使用数据并传递给您编写的组件的主要思想,将 app-advertising 组件转换为 '哑巴,只接收数据并渲染它。

【讨论】:

  • 好方法。我将尝试实施它。在这种情况下,我必须接触所有具有广告的子组件的父组件,对吗?在这种情况下,网站很大,有许多不同的父组件,如 Home、Article、Video、Galery、Sections 等。每一个都有子组件。
【解决方案3】:

尝试不同方法后我自己的答案。

  • 考虑到组件advertising.component 具有不同的广告位置并用于不同的模板(如article.component.htmlheader.component.htmlvideo.component.html 等)。例如:

    <!-- in article component, this one: -->
    <app-advertising adPos="x22" adDisp="mobile"></app-advertising>
    <app-advertising adPos="x23" adDisp="mobile"></app-advertising>
    
    <!-- in video component, this one: -->
    <app-advertising adPos="Position1" adDisp="desktop"></app-advertising>
    <app-advertising adPos="x94" adDisp="desktop"></app-advertising>
    
    <!-- in header component, this one: -->
    <app-advertising adPos="x95" adDisp="desktop"></app-advertising>
    
  • 显然 Angular 使用单例模式,所有组件/模板都使用相同的广告服务实例。因此,在我的advertising.service 中,我创建了一个private listPos: Map&lt;string, AdvertisingComponent&gt; = new Map();,在其中添加了所有广告位置。

    import { Injectable } from '@angular/core';
    import {AdItemModel, AdModel} from './ad.model';
    import {HttpClient} from '@angular/common/http';
    import {AdvertisingComponent} from './advertising.component';
    
    @Injectable({
      providedIn: 'root'
    })
    export class AdvertisingService {
    
      /**
       * List of positions(advertising) and component instances.
       * @type {Map<string, AdvertisingComponent>}
       */
      private listPos: Map<string, AdvertisingComponent> = new Map();
    
      /**
       * @constructor
       * @param {HttpClient} http (injectable)
       */
      constructor(private http: HttpClient) { }
    
      /**
       * Add position and component instance in the map.
       * Example of position: x22, x95, Position1, etc.
       * @param {string} adPos
       * @param {AdvertisingComponent} element
       * @return void
       */
      public registerPos(adPos: string, element: AdvertisingComponent): void {
        this.listPos.set(adPos, element);
        console.log('Add: ' + Array.from(this.listPos.keys()));
      }
    
      /**
       * Get ads from AdServer. Jsonp request.
       * @param {number} sleepMs
       * @return void
       */
      public getAds(sleepMs: number): void {
    
        setTimeout(() => { // wait for DOM rendering
    
          /**
           * Check if advertising position exist
           */
          if (this.listPos.size === 0) {
            return;
          }
    
          const url = 'http://your-ad-server-url-here@' + Array.from(this.listPos.keys());
    
          this.http.jsonp<AdModel>(url, '_RM_HTML_CALLBACK_').subscribe((response: AdModel) => {
    
            // process all ads
            this.process(response.Ad);
    
            // clean map
            this.listPos.clear();
    
          });
    
        }, sleepMs);
    
      }
    
      /**
       * Process list of advertising and publish them in their respecive position in the templates.
       * @param {AdItemModel[]} items
       * @return void
       */
      private process(items: AdItemModel[]): void {
    
        items.forEach((value: AdItemModel) => {
    
          /**
           * Get the 'AdvertisingComponent' instance from the Map and print the advertising there.
           * @type {V | undefined}
           */
          const adComponentInst: AdvertisingComponent = this.listPos.get(value.Pos);
          if (adComponentInst !== null) {
            adComponentInst.ad = value.SOMETHING; // the value object depends on your AdServer
          }
    
        });
    
      }
    
    }
    
  • 在我的advertising.component 中,我唯一要做的就是将位置(adPos)参数标签和组件实例添加到服务Map

    import {Component, Input, OnDestroy, OnInit} from '@angular/core';
    import {AdvertisingService} from './advertising.service';
    
    @Component({
      selector: 'app-advertising',
      templateUrl: './advertising.component.html',
      styleUrls: ['./advertising.component.css']
    })
    export class AdvertisingComponent implements OnInit {
    
      @Input() adPos: string;
      @Input() adDisp: string;
      public ad = '';
    
      /**
       * @constructor
       * @param {AdvertisingService} adService
       */
      constructor(private adService: AdvertisingService) {}
    
      ngOnInit() {
        /**
         * Register the current position and instance in the Advertising Service
         */
        this.adService.registerPos(this.adPos, this);
      }
    
    }
    
  • 在我的AppComponent 中,当事件NavigationEnd 被捕获时,我调用advertising.service 从 AdServer 获取所有位置一起(只发出一个请求),并将所有结果添加到相应的实例中位置。

    import {Component} from '@angular/core';
    import {NavigationEnd, Router} from '@angular/router';
    import {AdvertisingService} from './advertising/advertising.service';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent {
    
      title = 'Website Beta';
    
      /**
       * @constructor
       * @param {Router} router
       * @param {AdvertisingService} adService
       */
      constructor(private router: Router, private adService: AdvertisingService) {
    
        /**
         * Detect route changes
         */
        this.router.events.subscribe(event => {
          //  console.log(event.constructor.name);
          if (event instanceof NavigationEnd) {
    
            /**
             * Execute advertising after a few miliseconds
             */
            this.adService.getAds(500);
    
          }
        });
    
      }
    
    }
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多