代码之家  ›  专栏  ›  技术社区  ›  Manuel Huber

IE11上的Angular 4性能/CPU使用率

  •  2
  • Manuel Huber  · 技术社区  · 8 年前

    我正在开发angular 4应用程序。它在chrome&上运行良好;但是在IE11上的性能和加载时间是不可接受的。Chrome/FF上的路由器更改约为0.5s(对于更精细的页面),而IE11上的路由器更改约为5s。打开下拉列表(通过添加/删除要设置的CSS类 display:none )在Chrome/FF上是即时的,在IE11上大约需要3秒。
    打开下拉列表时,IE11探查器显示以下内容:
    1 2
    时间表上充满了 classList.add() 和 classList.remove() 电话:
    1 2
    这是同一对元素,在这些元素上一次又一次地添加/删除类。按钮

    下拉菜单仅使用 [ngClass] 指令:

      <div class="dropdown-menu"
           [ngClass]="{
           'show': open,
           'mod-dropup': dropup,
           'mod-right': rightAlign
           }">
        <ng-content></ng-content>
      </div>
    

    我在 polyfills.ts . 这可能是什么原因?

    版本:

    Internet Explorer 11.1884.14393.0

    1 回复  |  直到 8 年前
        1
  •  2
  •   Manuel Huber    8 年前

    原来问题是文档事件侦听器太多。

    我有一个onClickOutside指令,它注册了一个文档点击监听器,表中的每个条目都有一个下拉菜单,使用这个指令。因此,当我显示100个条目时,每次单击任意位置都会触发100个事件侦听器。

    我优化了这一点,在click服务中只有一个文档click侦听器,并且指令只(取消)向服务注册元素。

    服务内容如下:

    /**
     * A event emitter that should be notified about some kind of click related to the element
     */
    export interface ClickListener {
      element : ElementRef;
      emitter : EventEmitter<Event>;
    }
    
    /**
     * A central service for managing click handlers
     * This is mainly an optimization to reduce the amount of global click event handler
     */
    @Injectable()
    export class ClickService {
    
      private clickOutsideListeners : ClickListener[] = [];
    
      constructor() {
        this.registerClickHandlers();
      }
    
      private registerClickHandlers() : void {
        document.addEventListener('click', (event : Event) => {
          this.handleClickOutside(event);
        });
      }
    
      /**
       * Emits for every registered callback if the click is outside of the element
       */
      private handleClickOutside(event : Event) : void {
        this.clickOutsideListeners
          .filter(entry => !entry.element.nativeElement.contains(event.target))
          .forEach(entry => {
            entry.emitter.emit(event);
          });
      }
    
      /**
       * Registers a listener to be notified whenever there is a click outside of the element
       */
      public addOutsideClickListener(element : ClickListener) : void {
        if (this.clickOutsideListeners.indexOf(element) !== -1) return;
        this.clickOutsideListeners.push(element);
      }
    
      /**
       * Unregisters the listener
       */
      public removeOutsideClickListener(element : ClickListener) : void {
        const index = this.clickOutsideListeners.findIndex(entry => entry === element);
        if (index === -1) return;
        this.clickOutsideListeners.splice(index, 1);
      }
    }
    

    指令:

    /**
     * Emits a event when there has been a click outside of the host element
     */
    @Directive({
      selector: '[mdeOnClickOutside]',
    })
    export class OnClickOutsideDirective implements OnInit, OnDestroy {
    
      @Output() mdeOnClickOutside : EventEmitter<Event> = new EventEmitter();
    
      /**
       * (Un-)registers a click listener with the global click service
       */
      @Input() set mdeOnClickOutsideActive(active : boolean) {
        this.inputReceived = true;
        const clickCallback = {
          element: this.element,
          emitter: this.mdeOnClickOutside,
        };
        if (active) {
          this.clickService.addOutsideClickListener(clickCallback);
        } else {
          this.clickService.removeOutsideClickListener(clickCallback);
        }
      }
    
      private inputReceived : boolean;
    
      constructor(private element : ElementRef, private clickService : ClickService) {
      }
    
      /**
       * Activates click listener if it has not explicitly been set
       */
      ngOnInit() : void {
        if (this.inputReceived) return;
        this.mdeOnClickOutsideActive = true;
      }
    
      ngOnDestroy() : void {
        this.mdeOnClickOutsideActive = false;
      }
    
    }
    

    然后在其他组件的模板中使用它:

    <div (mdeOnClickOutside)="clickOutside()">Something</div>
    

    具有组件中的功能:

    clickOutside() {
        console.log('Somebody clicked somwhere outside');
      }