组件重新加载会增加HTTP请求的数量

时间:2018-01-30 13:52:07

标签: angular http routing request components

我正在为ImpressPages构建Angular(5.2.2)应用程序,我对HTTP请求有优化问题。我的应用程序结构如下所示:

Angular Structure

container.component.html

<div *ngIf="layout">
  <app-news *ngIf="layout == 'NewsComponent'" [hidden]="layout != 'NewsComponent'"></app-news>
  <app-main *ngIf="layout == 'MainComponent'" [hidden]="layout != 'MainComponent'"></app-main>
  <app-home *ngIf="layout == 'HomeComponent'" [hidden]="layout != 'HomeComponent'"></app-home>
</div>

container.component.ts

import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';



@Component({
  selector: 'app-container',
  templateUrl: './container.component.html',
})
export class ContainerComponent{
  layout: string;

  constructor(private route : ActivatedRoute) { }

  ngOnInit() {

    this.route.data.subscribe((response: {layout: string}) => {
      this.layout = response.layout;
    }, (error) => {
      console.log(error);
    })
  }
}

main.component.ts

Home,News等其他组件看起来相同 - 只有用于API更改的URL和HTML中的布局

import { Component } from '@angular/core';
import { ActivatedRoute } from "@angular/router";
import { ServerService } from '../../services/server.service';
import { SeoService } from '../../services/seo.service';
import { Config } from '../../config';


interface pageData {
  banner: string;
  data: any;
  html: string;
  text: string;
  title: string;
}

@Component({
  selector: 'app-main',
  templateUrl: './main.component.html',
  providers: [Config, ServerService, SeoService]
})
export class MainComponent {

  URL: string;
  langUrl: string;
  active: string;
  pageData: pageData;
  headerText: Object;



  constructor(private config: Config, private route: ActivatedRoute, private service: ServerService, private seo: SeoService) {
    this.URL = this.config.URL;
    this.langUrl = this.config.getLanguage();

  }

  ngAfterViewInit(): void {


    this.route.params.subscribe( params => {

      if(params.lang != this.langUrl) {
        this.langUrl = params.lang;
      }


      let siteTitle = params.index;

      if(typeof siteTitle != 'undefined') {
          siteTitle = siteTitle.replace('.html', ' ');
          siteTitle = siteTitle.replace(/-/g,' ');
      }


      this.service.getResponse(`${this.URL}/getContent/${params.index}/${this.langUrl}/0`).subscribe(
        (response: any) => {
            this.pageData = response;
            this.seo.generateTags({
              lang: this.langUrl,
              title : siteTitle,
              image : `${this.URL}/file/repository/${this.pageData.banner}`,
              slug : params.index
          })
        }, (error) => {
            console.log(error);
        }
      );
   });
  }
}

还有问题。当我第一次加载网站时,HTTP请求如下所示:

HTTP requests #1

然后,当我用其他布局(其他组件)转到其他页面时。每次我尝试进入和离开该页面时,HTTP请求都会增加1。首先输入:

HTTP requests #2

还有一次:

HTTP requests #3

(每当我清除网络标签时)

有没有更好的方法来实现我的想法?我需要在同一路径上管理组件取决于哪个布局API将返回,它必须是动态的。我无法创建/ home /:lang /:pageName或/ main /:lang /:pageName等链接。网址必须与ImpressPages CMS类似。

(服务工作者不会从API缓存数据 - 我还没有购买HTTPS,不要看它)

我希望我已经解释得很好。 谢谢你的回答。

修改

我现在遇到动态组件加载问题(https://angular.io/guide/dynamic-component-loader)。当我尝试通过 createComponent()方法执行此操作时,它会将我的组件数量增加一个。当我尝试通过 insert()方法执行此操作时,我收到错误:

`Cannot set property 'viewContainerParent' of undefined`

这是我的代码:

import { Component, ComponentFactoryResolver, ViewChild, ViewContainerRef } from '@angular/core';
import { ActivatedRoute } from '@angular/router';


import { NewsComponent } from '../components/news/news.component';
import { MainComponent } from '../components/main/main.component';
import { HomeComponent } from '../components/home/home.component';

import { ContainerDirective } from '../directives/container.directive';

// Directive
import { AfterViewInit } from '@angular/core/src/metadata/lifecycle_hooks';



export const entryComponentsMap = {
  'NewsComponent': NewsComponent,
  'MainComponent': MainComponent,
  'HomeComponent': HomeComponent
};  // Add Layout here


@Component({
  selector: 'app-container',
  templateUrl: './container.component.html',
})



export class ContainerComponent implements AfterViewInit{
  @ViewChild('container', {read: ViewContainerRef}) container : ViewContainerRef;

  layout: any;
  component: any;

  constructor(private route : ActivatedRoute, private componentFactoryResolver: ComponentFactoryResolver) { 
  }

  ngOnInit() {
  }

  ngAfterViewInit() {
    this.route.data.subscribe((response: {layout: string}) => {
      this.layout = response.layout;
      this.loadComponent(this.layout);
    }, (error) => {
      console.log(error); 
    })

  }

  loadComponent(layout) {
      let componentFactory = this.componentFactoryResolver.resolveComponentFactory(entryComponentsMap[layout]);
      this.container.insert(entryComponentsMap[layout], 0);
      this.component = this.container.createComponent(componentFactory);


  }

  ngOnChanges() {
    console.log(this)
    this.component.destroy();
  }
}

任何解决方案?

1 个答案:

答案 0 :(得分:0)

最后我找到了解决方案。路由参数订阅加载了两次。从一次加载的每3个组件发出请求。我刚刚使用unsubsribe()并在组件处于视图中时减少api调用。

工作示例:

import { Component } from '@angular/core';
import { ActivatedRoute } from "@angular/router";
import { Config } from "../../config";
import { ServerService } from "../../services/server.service";
import { SeoService } from "../../services/seo.service";
import { OnDestroy } from '@angular/core/src/metadata/lifecycle_hooks';
import { ISubscription } from 'rxjs/Subscription';





interface pageData {
  banner: string;
  data: any;
  html: string;
  text: string;
  title: string;
}

@Component({
  selector: 'app-news',
  templateUrl: './news.component.html',
  styleUrls: ['./news.component.less'],
  providers : [Config, ServerService, SeoService],
})


export class NewsComponent implements OnDestroy {
  subscription: ISubscription;
  subscriptionHTTP: ISubscription;

  URL: string;
  langUrl: string;
  active: string;
  pageData: pageData;
  headerText: Object;



  constructor(private config: Config, private route: ActivatedRoute, private service: ServerService, private seo: SeoService) {
    this.URL = this.config.impressURL;
    this.langUrl = this.config.getLanguage();

    this.subscription = this.route.params.subscribe( params => {

      if(params.lang != this.langUrl) {
        this.langUrl = params.lang;
      }

      let siteTitle = params.index;

      if(typeof siteTitle != 'undefined') {
          siteTitle = siteTitle.replace('.html', ' ');
          siteTitle = siteTitle.replace(/-/g,' ');
      }


     this.subscriptionHTTP = this.service.getResponse(`${this.URL}/getContent/${params.index}/${this.langUrl}/0`).subscribe(
        (response: any) => {
            this.pageData = response;
            this.seo.generateTags({
              lang: this.langUrl,
              title : siteTitle,
              image : `${this.URL}/file/repository/${this.pageData.banner}`,
              slug : params.index
          })
        }, (error) => {
            console.log(error);
        }
      ); 
   });
  }

  ngOnInit(): void {

  }

  ngOnDestroy() {
    if(this.subscription) this.subscription.unsubscribe();
    if(this.subscriptionHTTP)  this.subscriptionHTTP.unsubscribe();
  }

  hideOnClick(element, target) {
    element.parentNode.parentNode.classList.remove('in');
  }
}

我也尝试过这种方式:https://angular.io/guide/dynamic-component-loader,但我的方式要快得多。组件在开始时加载,而不是在路由更改时加载。