angular实现textarea动态实现增加减少

重点实现了默认开始的时候高度一致,不会导致开始的时候textarea的高度展开的问题

textarea实现自动增加减少高度,

<textarea #textarea
          class="smart-textarea"
          [(ngModel)]="content"
          (input)="adjustHeight()"
          placeholder="Start typing..."
></textarea>

.smart-textarea {
  width: 100%;
  min-height: 1.2lh; /* 使用lh单位确保基础高度 */
  line-height: 1.6; /* 必须与hiddenDiv的line-height一致 */
  margin: 0;
  box-sizing: border-box;
  font-family: inherit;
  font-size: 16px;
  resize: none;
  overflow-y: hidden;
}

.height-calculator {
  position: absolute;
  visibility: hidden;
  white-space: pre-wrap;
  word-wrap: break-word;
  pointer-events: none;
}

//.smart-textarea {
//  transition: height 0.15s ease-out;
//}

 @ViewChild('textarea') textareaRef!: ElementRef<HTMLTextAreaElement>;
  content = '';
  private calculator!: HTMLElement;
  private baseHeight = 0;

  // 监听窗口变化,调整高度
  @HostListener('window:resize')
  onWindowResize() {
    this.adjustHeight(true);
  }

  ngAfterViewInit() {
    this.initHeightCalculator();
    this.setBaseHeight();
    this.adjustHeight(true); // 强制初始调整
  }

  ngOnDestroy() {
    if (this.calculator && this.calculator.parentNode) {
      document.body.removeChild(this.calculator);
    }
  }

  private initHeightCalculator() {
    this.calculator = document.createElement('div');
    this.calculator.className = 'height-calculator';

    const textarea = this.textareaRef.nativeElement;
    const textareaStyle = window.getComputedStyle(textarea);

    // 安全复制样式属性,避免 TS7015 错误
    const styleProperties: (keyof CSSStyleDeclaration)[] = [
      'font', 'letterSpacing', 'wordSpacing', 'textTransform',
      'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',
      'borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth',
      'width', 'boxSizing'
    ];

    for (const prop of styleProperties) {
      const value = textareaStyle[prop];
      if (typeof value === 'string') {
        this.calculator.style.setProperty(
          prop.toString(),
          value
        );
      }
    }

    this.calculator.style.overflow = 'hidden';
    this.calculator.style.position = 'absolute';
    this.calculator.style.visibility = 'hidden';
    this.calculator.style.whiteSpace = 'pre-wrap';
    this.calculator.style.wordWrap = 'break-word';
    document.body.appendChild(this.calculator);
  }

  private setBaseHeight() {
    // 获取真实的单行高度(包括 padding)
    this.calculator.textContent = ' ';
    this.baseHeight = this.calculator.offsetHeight;

    // 设置 textarea 最小高度为单行高度
    this.textareaRef.nativeElement.style.minHeight = `${this.baseHeight}px`;
  }

  adjustHeight(force = false) {
    const textarea = this.textareaRef.nativeElement;
    if (!force && textarea.value === '') return;

    // 同步宽度以防止换行计算错误
    this.calculator.style.width = `${textarea.clientWidth}px`;

    // 确保换行符被正确渲染
    this.calculator.textContent = textarea.value + '\n';

    // 计算新高度并设置到 textarea 上
    const newHeight = Math.max(this.calculator.offsetHeight, this.baseHeight);
    textarea.style.height = 'auto';
    textarea.style.height = `${newHeight}px`;
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值