通过指令使用省略号...来截断文本支持单行和多行省略

76 阅读1分钟
适用范围:行内元素、行内块元素;(注意多行文本可能存在浏览器内核版本限制)
使用css的属性实现
  • overflow、whiteSpace、textOverflow进行单行文本的省略号...显示;
  • webkitBoxOrient 、webkitLineClamp、textOverflow进行多行文本缩略,(主要用webkitLineClamp)
import { Directive, ElementRef, AfterViewInit, Input } from '@angular/core';
@Directive({
  selector: '[textEllipsis]',
})
export class TextEllipsisDirective implements AfterViewInit {
  @Input() lineClamp: string | undefined;
  constructor(private elementRef: ElementRef) {}
  ngAfterViewInit() {
    const element: HTMLElement = this.elementRef.nativeElement;
    this.setEllipsis(element, this.lineClamp);
    this.checkOverflow(element);
  }
  setEllipsis(element, lineClamp) {
    if (!lineClamp || lineClamp === '1') {
      element.style.overflow = 'hidden';
      element.style.whiteSpace = 'nowrap';
      element.style.textOverflow = 'ellipsis';
    } else {
      element.style.overflow = 'hidden';
      element.style.display = '-webkit-box';
      element.style.webkitBoxOrient = 'vertical';
      element.style.webkitLineClamp = this.lineClamp ?? '2';
      element.style.textOverflow = 'ellipsis';
    }
  }
  private checkOverflow(element: HTMLElement) {
    let widthOrHeight =
      !this.lineClamp || this.lineClamp === '1' ? 'Width' : 'Height';
    setTimeout(() => {
      if (
        element[`scroll${widthOrHeight}`] > element[`client${widthOrHeight}`]
      ) {
        element.title = element.textContent.trim();
      }
    });
  }
}

angular中替换setTimeout,使用ChangeDetectorRef确保视图更新完成后再进行变更检查

import { Directive, ElementRef, AfterViewInit, ChangeDetectorRef, Input } from '@angular/core';
@Directive({
  selector: '[textEllipsis]',
})
export class TextEllipsisDirective implements AfterViewInit {
  @Input() lineClamp: string | undefined;
  constructor(
    private elementRef: ElementRef,
    private cdr: ChangeDetectorRef // 注入 ChangeDetectorRef
  ) {}
  ngAfterViewInit() {
    const element: HTMLElement = this.elementRef.nativeElement;
    this.setEllipsis(element, this.lineClamp);
    // 直接调用 checkOverflow,确保元素已渲染完成
    this.checkOverflow(element);
  }
  setEllipsis(element: HTMLElement, lineClamp: string | undefined) {
    if (!lineClamp || lineClamp === '1') {
      element.style.overflow = 'hidden';
      element.style.whiteSpace = 'nowrap';
      element.style.textOverflow = 'ellipsis';
    } else {
      element.style.overflow = 'hidden';
      element.style.display = '-webkit-box';
      element.style.webkitBoxOrient = 'vertical';
      element.style.webkitLineClamp = this.lineClamp ?? '2';
      element.style.textOverflow = 'ellipsis';
    }
  }
  private checkOverflow(element: HTMLElement) {
    let widthOrHeight =
      !this.lineClamp || this.lineClamp === '1' ? 'Width' : 'Height';
    this.cdr.detectChanges(); // 强制变更检测,确保视图更新完成
    if (
      element[`scroll${widthOrHeight}`] > element[`client${widthOrHeight}`]
    ) {
      element.title = element.textContent?.trim() ?? '';
    }
  }
}