我有一个 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);
}
});
}
};
好吧,我找到了答案。 我不需要在事件上调用 preventDefault。 通常这是一条被忽视的线。
在不调用 preventDefault 的情况下,Textarea 会像宣传的那样工作。
我可以建议,您可以将您的功能放入
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>
请注意,粘贴后自动剪切文本会导致用户无法识别并发送剪切后的数据。通常最好让他们粘贴并将字段标记为无效。