mouseenter / mouseleave с @HostListener

Мерцание убивает меня, и после прочтения всех тем, связанных с jQuery, и mdn, я все еще не могу понять это.

Итак, у меня есть эта @Directive для отображения всплывающей подсказки, и вот как я привязываю ее к элементам:

  @HostListener('mouseenter', ['$event']) onEnter( e: MouseEvent ) {
    this.showTooltip(e);
  }

  @HostListener('mouseleave', ['$event']) onLeave( e: MouseEvent ) {
    this.hideTooltip(e);
  }

  @HostListener('click', ['$event']) onClick( e: MouseEvent ) {
    this.hideTooltip(e);
  }

  constructor(
    private el: ElementRef,
    private renderer: Renderer2,
    private coordsService: CoordsService,
    @Inject(DOCUMENT) doc
  ) {
    this.docBody = doc.body;
  }

  public ngAfterViewInit(): void {
    this.tooltipContainer = this.renderer.createElement('div');
    this.renderer.addClass( this.tooltipContainer, 'tooltip--tip');
    this.renderer.addClass( this.tooltipContainer, 'tooltip--pos_' + this.position);
  }

  public showTooltip( e: MouseEvent ): void {

    if ( this.tooltip !== null ) {

      // text 
      this.selectedTooltip = this.renderer.createText( this.tooltip );

      // append to body
      this.renderer.appendChild( this.tooltipContainer, this.selectedTooltip);
      this.renderer.appendChild( this.docBody, this.tooltipContainer );

      // target element
      const target: HTMLElement = <HTMLElement>e.target;
      const bbox: ClientRect = target.getBoundingClientRect();

      // the array holds the pixel position of the property; should sync with top:left
      let coords: ElementCoords = this.coordsService.setPositionCoords(bbox, this.position, this.tooltipContainer, { left: -6 } );

      // write position
      this.renderer.setStyle( this.tooltipContainer, 'top', coords.top+'px' );
      this.renderer.setStyle( this.tooltipContainer, 'left', coords.left+'px' );
    }

  }

  public hideTooltip( e: MouseEvent ): void {
    if ( this.selectedTooltip ) {
      this.renderer.removeChild ( this.tooltipContainer, this.selectedTooltip);
      this.renderer.removeChild( this.docBody, this.tooltipContainer );
      this.selectedTooltip = null;
    }
  }

Каждый <span>, содержащий текст, мерцает. Каждый селектор, в котором есть SVG, мерцает... Есть идеи?

PS. Почему-то el: ElementRef не используется, хотя я почему-то его ввел. Пытался сопоставить ссылку на него - все равно не повезло.


person pop    schedule 23.11.2018    source источник
comment
звучит так, как будто ваш tooltipContainer вызывает выход из мыши, потому что он находится над элементом. Если вы не возражаете, что вы не можете ничего нажать там. Установите в вашем css pointer-events: none для tooltipContainer   -  person Poul Kruijt    schedule 24.11.2018
comment
Что ж, это помогло, спасибо! Но почему он вообще что-то запускает, если я привязываю событие к какому-то другому элементу?   -  person pop    schedule 24.11.2018


Ответы (1)


Ваш tooltipContainer вызывает mouseleave, потому что он находится над элементом. Если вы не возражаете, что вы не можете ничего щелкнуть/выбрать там. Установите в вашем css pointer-events: none для tooltipContainer.

Вы вводите элемент с помощью директивы (mouseenter), контейнер всплывающей подсказки проходит по этому элементу. Теперь всплывающая подсказка имеет над ним курсор. Ага! Это вызывает (mouseleave) из элемента с директивой, поэтому всплывающая подсказка исчезает. Но эй, курсор снова не в директиве... (ввод мыши)!... но эй! всплывающая подсказка снова находится под курсором... (mouseleave)... и т.д. :)

С помощью событий-указателей вы гарантируете, что накладывающийся элемент не получает четных значений, и они срабатывают для элемента под ним. Однако вы также можете попытаться сделать так, чтобы всплывающая подсказка не перекрывала элемент, но это на ваше усмотрение.

person Poul Kruijt    schedule 23.11.2018