Angular 6 - 如何一起处理所有组件?不是单独的

时间:2018-06-06 15:53:33

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

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

ROW_NUMBER

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

但我们的AdServer也支持1个请求,并且所有adPos都已连接在一起。但要做到这一点,我需要阅读所有组件标签,并为所有这些标签提出1个请求。我怎么能用Angular 2 +做到这一点?

3 个答案:

答案 0 :(得分: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组件转换为一个'哑',只接收数据并呈现它。

答案 1 :(得分:0)

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

  • 考虑到组件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<string, AdvertisingComponent> = 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);
    
          }
        });
    
      }
    
    }
    

答案 2 :(得分:-1)

将广告放入数组然后循环播放。

这样的事情:

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