Angular * ngIf в компоненте с привязкой к методу ngStyle?

Я использую Angular 5, хотя не знаю, связана ли моя проблема с версией или Angular или с тем, как я кодировал свои компоненты.

Я создаю компонент, который выглядит и ведет себя как таблица. Он состоит из двух основных частей: панели инструментов и самой таблицы. Вот упрощенный образец моего шаблона:

<div class="list__table">

<!-- The toolbar -->
  <div class="list-toolbar__wrapper" *ngIf="hasToolbar">
      <div class="list-toolbar">
          <div class="list-toolbar__right-column">
            <div class="list-toolbar__right-column__conditional">
              <toolbar-root [settings]="getToolbarItemsA()" i18nStrings="" [svgIconsPath]="svgIconsPath()"></toolbar-root>
            </div>
            <div class="list-toolbar__right-column__action">
              <toolbar-root [settings]="getToolbarItemsB()" i18nStrings="" [svgIconsPath]="svgIconsPath()"></toolbar-root>
            </div>
          </div>
      </div>
  </div>
  <!-- end of toolbar -->

  <!-- Begining of content -->
  <div>
    <!-- Table head -->
    <div
      class="list__table__header"
      [style.padding-right]="hasScrollbar ? scrollbarWidth : 0">
      <div class="list-row list-row--head">
        <span
          class="list-checkbox list-row__checkbox"
          [ngClass]="{'list-checkbox--checked': areAllRowsSelected, 'list-checkbox--indeterminate': areSomeRowsSelected}"
          *ngIf="hasToolbar"
          (click)="toggleAllChecked()">
            <span class="list-checkbox__box"></span>
            <svg class="list-checkbox__checked-mark">
              <use xlink:href="#NotificationValidation" />
            </svg>
            <svg class="list-checkbox__indeterminate-mark">
              <use xlink:href="#IndeterminateCheckbox" />
            </svg>
          </span>
        <span
          *ngFor="let column of getVisibleColumns()"
          class="list-row__data list-row__data--{{column.size}}"
          (click)="changeSelectedColumnSortingState(column.prop)">
          <div class="list-row__data__text" [ngClass]="{'list-row__data__text--selected' : column.prop == selectedColumn}">
            {{column.name}}
          </div>
        </span>
      </div>
    </div>
    <!-- end of table head -->

    <!-- Content rows -->
    <div class="list__table__content" id="scrollableTableContent">
      <!-- Repeatable rows -->
      <div
        class="list-row"
        [ngClass]="{'list-row--selected': row.isSelected, 'list-row--selectable' : hasToolbar}"
        *ngFor="let row of visibleRows | slice:0:20; index as i"
        (click)="toggleSelectedRow(i)">
          <span
            class="list-checkbox list-row__checkbox"
            *ngIf="hasToolbar"
            [ngClass]="{'list-checkbox--checked': row.isSelected}">
            <span class="list-checkbox__box"></span>
            <svg class="list-checkbox__checked-mark">
              <use xlink:href="#NotificationValidation" />
            </svg>
          </span>
          <span
            class="list-row__data list-row__data--{{column.size}}"
            *ngFor="let column of getVisibleColumns()">
            <div class="list-row__data__text" *ngIf="row[column.prop]">{{row[column.prop]}}</div>
          </span>
      </div>
      <!-- end of repeatable rows -->
    </div>
    <!-- end of content rows -->
  </div>
  <!-- end of content -->
</div>

Как видите, я использую директиву * ngIf в list-toolbar__wrapper, чтобы контролировать наличие панели инструментов в DOM. hasToolbar установлен в true в классе моего компонента следующим образом: public hasToolbar: boolean = true

Однако, независимо от значения hasToolbar, в тот момент, когда я использую *ngIf в своем шаблоне, я получаю некоторые странные визуальные «глюки». Мои list-row__data на заголовке таблицы «мигают» при любом действии (например, наведении курсора, щелчке) на панели инструментов, самих себя и моих строк содержимого. Углубившись в проблему, я выяснил, что вызывает такое поведение, но не понимаю, почему это происходит. Компонент toolbar-root имеет сам компонент toolbar-item, который, наконец, содержит мой компонент ripple-root, и его шаблон выглядит следующим образом:

<div #ripple class="entity-header-ripple" (click)="handleClick()" (mousedown)="handleMouseDown($event)" [style.borderRadius]="getBorderRadius()" [ngClass]="{'entity-header-ripple--clicked': isClicked}">
    <div class="entity-header-ripple__circle" [style.backgroundColor]="color" [style.width.px]="getCircleDiameter()" [style.height.px]="getCircleDiameter()" [style.top.px]="getTopPosition()" [style.left.px]="getLeftPosition()" [ngStyle]="{'transformorigin': 2, '-webkit-transform-origin': 2}"></div>
</div>

Когда я изменяю каждый бит кода с помощью [style] или [ngStyle], который назначен методу (getBorderRadius(), getCircleDiameter(), getTopPosition(), getLeftPosition()), и даю им статические значения (например, «20»), проблем с миганием больше не возникает.

Мне нужно, чтобы моя панель инструментов была условной, и я хотел бы оставить свой компонент ряби как есть или с небольшими изменениями. В целом, я хотел бы понять, что вызывает проблему, чтобы ее решить.


person Stephe    schedule 22.02.2018    source источник


Ответы (1)


Проблема с вызовами функций в шаблоне заключается в том, что они вызываются каждый раз при обнаружении изменений, т.е. любое событие. Вы можете просто использовать свойства вместо методов или лучше: Observables / BehaviorSubjects с асинхронным конвейером, который будет обрабатывать обнаружение изменений, позволяя вам использовать OnPush.

<div *ngIf="vars$|async as vars">
    <div [style.top.px]="vars.top"/>
</div>

initialState = {top:0, left:0, etc: 'etc'};
vars$:BehaviorSubject<any> = new BehaviorSubject(initialState);
// Send next object, keep it immutable
this.vars$.next(Object.assign({}, this.vars$.getValue(), {top:5}));
person funkizer    schedule 22.02.2018