首页 文章

当点击路线时,Angular2应用程序会冻结

提问于
浏览
4

我正在为我的实习开发一个Angular2应用程序,我的一个组件遇到了一个真正的问题 .

此组件是应用程序的主导航菜单,它是 recursive tree view ,其中每个组件实例包含到另一个组件的路由 .

这个组件适用于少数孩子,但在实际用例中,递归创建了大约300个孩子 . 当我单击菜单中的某个项目以显示另一个视图时,应用程序会冻结 . 处理路线似乎需要很长时间,而且我有超时时间 .

奇怪的是导航菜单本身的构造没有问题,但是当我尝试点击路线时它总是冻结 .

Edit :以下是关于plunker的一些文件 - > https://plnkr.co/edit/VMC2SSuL4iaNJAjQxQ0c?p=info

这是我的递归组件:

@Component({
  selector: 'tran-location-zippy',
  template : `<ul *ngIf="location">
                <li class="li-item li-device-container" 
                    [class.active]="isRouteActive(['LocationVueComponent', {code : location.code}])">
                    <a class="goTo" 
                        [routerLink]="['LocationVueComponent', {code : location.code}]">
                        <span class="glyphicon glyphicon-new-window"></span>
                    </a>
                    <div (click)="toggle()">
                        <span *ngIf="!visible && !isEmpty()" class="glyphicon glyphicon-chevron-down"></span>
                        <span *ngIf="visible && !isEmpty()" class="glyphicon glyphicon-chevron-up"></span>
                        {{location.label}}
                    </div>
                </li>
                <span [hidden]="!visible">
                    <li *ngFor="#subLocation of location.children" 
                        class="li-container">
                        <tran-location-zippy
                            [location]="subLocation">
                        </tran-location-zippy>
                    </li>
                </span>
            </ul>
            `,
  styleUrls : ['src/style/zippy-menu.style.css'],
  directives: [
    ROUTER_DIRECTIVES,
    LocationZippyComponent
  ]
})
export class LocationZippyComponent {

  @Input() location 

  visible : boolean

  constructor(private _router : Router) {
    this.visible = false
  }

  toggle() {
    this.visible = !this.visible
  }

  isEmpty() : boolean {
    return (this.location.hasOwnProperty('devices') || this.location.hasOwnProperty("children")) ? false : true
  }

  isRouteActive(route) : boolean {
    return this._router.isRouteActive(this._router.generate(route))
  }
};

这是我的数据结构:

export interface Location{
  code : string
  label : string
  type? : LocationType
  parent? : Location
  children? : Location[]
  devices? : Device[] 
}

这是我的路线:

@RouteConfig([
{
    path: '/',
    name: 'DefaultVueComponent',
    component: DefaultVueComponent,
    useAsDefault : true
},
{
    path: '/location/:code',
    name: 'LocationVueComponent',
    component: LocationVueComponent
},
{
    path: '/devices/types/:label',
    name: 'DeviceTypeVueComponent',
    component: DeviceTypeVueComponent
},
{
    path: '/device/:code',
    name: 'DeviceVueComponent',
    component: DeviceVueComponent
},
{
    path: '/state/:label',
    name: 'GlobalStateVueComponent',
    component: GlobalStateVueComponent
}
])

这是我通过单击菜单项调用的视图,它是一个调用2个子组件的基本组件 . 孩子们根据 queries Input 从服务器获取信息 .

@Component({
  selector: 'tran-location-vue',
  template: `
    <p>
        <label for="refresh-button">
            {{ ((refreshing) ? 'STOP_AUTO_RESFRESH' : 'START_AUTO_RESFRESH') | translate }}
        </label>
        <button id="refresh-button" type="button" class="btn btn-default" (click)="toggleRefreshButton()">
            <span class="glyphicon glyphicon-refresh"></span>
        </button>
    </p>
    <tran-global-state [queries]="[query]" [timingRefreshing]="5000" [refreshing]="refreshing">
    </tran-global-state>
    <tran-alarms-states [queries]="[query]" [timingRefreshing]="5000" [refreshing]="refreshing">
    </tran-alarms-states>
`,
  providers: [
      CategoriesService
  ],
  directives: [
    GlobalStateComponent,
    AlarmsStatesComponent
  ],
  pipes: [
    TranslatePipe
  ]
})
export class LocationVueComponent implements OnInit {

  query : QueryString

  refreshing : boolean

  constructor(
    private _routeParams : RouteParams
    ) {
    this.refreshing = true
  }

  ngOnInit() {
    let location = this._routeParams.get('code')
    this.query = {key: 'location', value: location}
  }

  toggleRefreshButton() {
      this.refreshing = !this.refreshing
  }
}

1 回答

  • 4

    我找到了解决问题的方法 . 我将 LocationZippyComponent 组件的 changeDetection 策略更改为 ChangeDetectionStrategy.OnPush ,并且不再冻结 . 我想Angular同时检测300个组件的变化是一个性能问题 .

相关问题