tdesign-vue-next icon indicating copy to clipboard operation
tdesign-vue-next copied to clipboard

[Textarea] 设置autosize+切换页面后会多出一个textarea

Open origin-coding opened this issue 1 year ago • 6 comments

tdesign-vue-next 版本

1.9.7

重现链接

https://github.com/origin-coding/Alacrity

重现步骤

复现步骤

  1. 下载最新版Alacrity,可以使用Windows的MIS或Exe安装包(手动编译运行需要Rust环境,搭建比较耗时)安装(运行需要至少需要Win10操作系统,这是Tauri的限制,与TDesign无关)。
  2. 打开Alacrity,选择任意一个带有Textarea的插件(比如文本哈希),然后悬浮在Textarea上。image image
  3. 在保持Focus的状态下浏览器后退(这一步可以使用鼠标的左侧按钮,部分鼠标左侧按钮有后退的功能)。 image image
  4. 此时页面左下角就会有一个额外的textarea元素。

复现注意事项

  1. 需要有Hover或者聚焦行为行为,没有的话直接后退不会复现,而且在后退时候需要保持这种状态,因此需要使用。
  2. 发现问题的元素的autosize属性需要设置为对象,不设置或者设置为true都不会触发。这一点在文本哈希里面有体现,页面右下角的Textarea在获取聚焦并后退之后不会触发上述问题。

期望结果

页面切换后不再显示这个Textarea,或者设置为display: none之类的属性让它不再显示

实际结果

No response

框架版本

Vue(3.4.31)

浏览器版本

No response

系统版本

No response

Node版本

No response

补充说明

No response

origin-coding avatar Aug 11 '24 09:08 origin-coding

👋 @origin-coding,感谢给 TDesign 提出了 issue。 请根据 issue 模版确保背景信息的完善,我们将调查并尽快回复你。

github-actions[bot] avatar Aug 11 '24 09:08 github-actions[bot]

这个额外的textarea元素是在calcTextareaHeight.ts文件的calcTextareaHeight函数中创建:

if (!hiddenTextarea) {
  hiddenTextarea = document.createElement('textarea');
  document.body.appendChild(hiddenTextarea);
}

销毁语句如下:

hiddenTextarea.parentNode && hiddenTextarea.parentNode.removeChild(hiddenTextarea);
hiddenTextarea = null;

而且在autosize属性设置为true或者不设置时没有问题,在textarea.tsx文件中,相关代码在adjustTextareaHeight函数中:

const adjustTextareaHeight = () => {
  if (props.autosize === true) {
    textareaStyle.value = calcTextareaHeight(refTextareaElem.value);  // autosize设置为true时调用只有一个参数
  } else if (props.autosize && typeof props.autosize === 'object') {
    const { minRows, maxRows } = props.autosize;
    textareaStyle.value = calcTextareaHeight(refTextareaElem.value, minRows, maxRows);  // autosize设置为对象时调用参数有3个
  } else if (attrs.rows) {
    textareaStyle.value = { height: 'auto', minHeight: 'auto' };
  } else if (attrs.style && refTextareaElem.value?.style?.height) {
    textareaStyle.value = { height: refTextareaElem.value.style.height };
  }
};

可以回过头,再次查看calcTextareaHeight函数,它的函数签名如下:

function calcTextareaHeight(
  targetElement: HTMLTextAreaElement, minRows: RowsType = 1, maxRows: RowsType = null,
)

调用参数只有一个时,minRows不为null,maxRows为null;调用参数有三个时,minRows和maxRows都不为null。 所以问题可能出在这一部分:

if (maxRows !== null) {
  let maxHeight = singleRowHeight * maxRows;
  if (boxSizing === 'border-box') {
    maxHeight = maxHeight + paddingSize + borderSize;
  }
  height = Math.min(maxHeight, height);
}

不过我并不是特别确定是不是这里的问题,我对于页面样式这部分不太了解。

origin-coding avatar Aug 11 '24 09:08 origin-coding

我在开发环境又尝试了一次,发现了下面的报错: image

origin-coding avatar Aug 11 '24 09:08 origin-coding

TDesign Vue Next的文档官网上面也可以复现这个bug,只不过textarea没有显示,元素实际存在,而且也有报错。 image image 可以复现的Textarea元素是基础多文本输入框的第三个Textarea元素,Hover之后按动鼠标后退键仍然能复现。

origin-coding avatar Aug 11 '24 10:08 origin-coding

谢谢反馈和提供思路 我们具体再排查下

uyarn avatar Aug 12 '24 02:08 uyarn

我这里在开发环境又试了一次,找到了调用堆栈: image 相关代码如下:

const emitBlur = (e: FocusEvent) => {
  adjustTextareaHeight();
  focused.value = false;
  props.onBlur?.(innerValue.value, { e });
  formItem?.handleBlur();
};

那么是不是可以在函数执行之前判断一下,如果target不存在的时候就不处理这个事件呢?:

const emitBlur = (e: FocusEvent) => {
  if (!e.target) return;
  adjustTextareaHeight();
  focused.value = false;
  props.onBlur?.(innerValue.value, { e });
  formItem?.handleBlur();
};

origin-coding avatar Aug 17 '24 05:08 origin-coding