带有 Vuetify Textarea 的浮动标签在粘贴和模糊后不会在 Textarea 上方重置

问题描述 投票:0回答:2

我有一个 Textarea 模糊问题,在粘贴后单击出 Textarea 后无法重新定位浮动标签。

我将一些文本粘贴到文本区域中,然后以任何方式退出文本区域(Ctrl-Enter 或在区域外单击),然后导致文本区域模糊,标签(例如摘要注释)不会移出文本区域,因为标签应该。相反,它保持不变并与粘贴的文本重叠。

只有在我离开 Textarea 之前进行手动击键时,标签才会在模糊时返回到 Textarea 上方的原始位置。

有解决这个问题的直接方法吗?在其他情况下(非 VUE 3),我会尝试手动触发 Textarea,但我认为我不能用 VUE DOM 做到这一点。

粘贴例程如下:

const textAreaPaste = (e: ClipboardEvent) => {
let clipboardData, pastedData;
let textResult = "";
const target = e.target as HTMLTextAreaElement;

if (e) {
    e.preventDefault();
    nextTick(() => {
        // Get pasted data via clipboard API
        clipboardData = e.clipboardData;
        pastedData = clipboardData ? clipboardData.getData("Text") : "";

        //Remove carriage returns
        const t1 = pastedData.replace(/\r(?!\n)|\n(?!\r)/g, "\n");

        // Insert the text in the correct editing position, if necessary
        if (e.target && (target.selectionStart || String(target.selectionStart) === "0")) {
            var startPos = target.selectionStart;
            var endPos = target.selectionEnd;
            textResult = target.value.substring(0, startPos) + t1 + target.value.substring(endPos, target.value.length);
        } else {
            textResult += t1;
        }
        // Truncate to max length
        (e.target as HTMLInputElement).value =
            textResult.length > maxAnnoLetter ? textResult.substr(0, maxAnnoLetter) : textResult;
        const attribs = (e.target as HTMLInputElement).attributes;
        const id = (attribs as HTMLAttributes).id;
        // Timeout on update necessary
        if (id) {
            setTimeout(() => {
                calcRemainingChars(id.nodeValue, textResult);
            }, 250);
        }
    });
}

};

vuejs3 textarea blur floating-labels
2个回答
0
投票

好吧,我找到了答案。 我不需要在事件上调用 preventDefault。 通常这是一条被忽视的线。

在不调用 preventDefault 的情况下,Textarea 会像宣传的那样工作。


0
投票

我可以建议,您可以将您的功能放入

paste
侦听器中,而不是使用可怕的
@input
事件。您在处理程序中执行的操作(替换
\r\n
和切割长度)也可以在那里完成,无需直接的 DOM 操作。

使用

:value
属性和
@input
侦听器而不是
v-model
来设置处理程序:

<v-textarea
  :value="textValue"
  @input="$event => textValue = adjustAfterPaste($event)"
></v-textarea>

您可以通过检查事件的

inputType
是否为
"insertFromPaste"
来检查输入是否来自粘贴:

const adjustAfterPaste = (e) => {
  const value = e.target.value
  return (e.inputType !== 'insertFromPaste') ? value : value
    .replace(/\r(?!\n)|\n(?!\r)/g, "\n")
    .substring(0, maxlength);
}

优点似乎非常明显(不必处理不可更改的事件,无需直接的 DOM 操作,不必手动执行粘贴,结构清晰,简洁)。但是这种方法有两个缺点:

  • 替换将在整个字符串上运行,而不仅仅是粘贴的内容,除非您通过比较旧值和新值来找出粘贴的内容
  • 与所有其他当前更改粘贴内容的方法一样,它会破坏撤消/重做

这是一个片段,我正在使用

toUpperCase()
使更改更加明显。再次注意,更改应用于整个字符串:

const { createApp, ref } = Vue;
const { createVuetify } = Vuetify
const vuetify = createVuetify()

const adjustAfterPaste = (e, maxlength) => {
  const value = e.target.value
  return (true || e.inputType !== 'insertFromPaste') ? value : value
    .toUpperCase()
    .substring(0, maxlength);
}

const App = {
  setup(){
    return {
      textValue: ref(''),
      maxlength: ref(50),
      adjustAfterPaste,
    }
  }
}
createApp(App).use(vuetify).mount('#app')
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/vuetify@3/dist/vuetify.min.css" />
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
<div id="app">
  <v-app>
    <v-main>
      <v-textarea
        label="textarea"
        :value="textValue"
        @input="textValue = adjustAfterPaste($event)"
        :maxlength="maxlength"
      ></v-textarea>
       Content: {{ textValue }}
    </v-main>
  </v-app>

</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@3/dist/vuetify.min.js"></script>


请注意,粘贴后自动剪切文本会导致用户无法识别并发送剪切后的数据。通常最好让他们粘贴并将字段标记为无效。

© www.soinside.com 2019 - 2024. All rights reserved.