perf: 暂时还原调整词语高亮组件

This commit is contained in:
rd
2025-09-10 16:04:35 +08:00
parent 48f23cfa02
commit ffed5cb152
2 changed files with 56 additions and 53 deletions

View File

@ -1,15 +1,15 @@
<template> <template>
<div class="highlight-textarea-container"> <div class="highlight-textarea-container">
<TextArea <a-textarea
ref="textareaWrapRef" ref="textareaWrapRef"
v-model:value="inputValue" v-model="inputValue"
placeholder="请输入作品描述" placeholder="请输入作品描述"
:disabled="disabled" :disabled="disabled"
showCount show-word-limit
:maxlength="1000" :max-length="1000"
size="large" size="large"
class="textarea-input h-full w-full" class="textarea-input h-full w-full"
@change="handleInput" @input="handleInput"
@focus="() => (focus = true)" @focus="() => (focus = true)"
@blur="() => (focus = false)" @blur="() => (focus = false)"
/> />
@ -25,8 +25,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Input } from 'ant-design-vue'; import { Input } from 'ant-design-vue';
import type { ElementEvent } from 'echarts'; const {TextArea} = Input
const { TextArea } = Input;
import { ref, computed, watch, defineProps, defineEmits, onMounted, onUnmounted } from 'vue'; import { ref, computed, watch, defineProps, defineEmits, onMounted, onUnmounted } from 'vue';
import { escapeRegExp } from './constants'; import { escapeRegExp } from './constants';
@ -70,8 +69,7 @@ watch(
); );
// 处理输入事件 // 处理输入事件
const handleInput = (e: any) => { const handleInput = (value: string) => {
const value = e.currentTarget.value;
emit('update:modelValue', value); emit('update:modelValue', value);
}; };
@ -117,9 +115,9 @@ const generateHighlightedHtml = (): string => {
onMounted(() => { onMounted(() => {
nativeTextarea = nativeTextarea =
(textareaWrapRef.value?.$el || textareaWrapRef.value)?.querySelector?.('textarea.ant-input') || (textareaWrapRef.value?.$el || textareaWrapRef.value)?.querySelector?.('textarea.arco-textarea') ||
document.querySelector('.textarea-input .ant-input'); document.querySelector('.textarea-input .arco-textarea');
if (nativeTextarea) { if (nativeTextarea) {
nativeTextarea.addEventListener('scroll', handleTextareaScroll); nativeTextarea.addEventListener('scroll', handleTextareaScroll);
nativeTextarea.addEventListener('compositionstart', handleCompositionUpdate); nativeTextarea.addEventListener('compositionstart', handleCompositionUpdate);
@ -147,9 +145,7 @@ const handleTextareaScroll = (e: Event) => {
}; };
const handleCompositionUpdate = () => { const handleCompositionUpdate = () => {
console.log('handleCompositionUpdate');
if (!nativeTextarea) return; if (!nativeTextarea) return;
// 使用 rAF 等待浏览器把最新字符写入 textarea.value 再读取 // 使用 rAF 等待浏览器把最新字符写入 textarea.value 再读取
requestAnimationFrame(() => { requestAnimationFrame(() => {
if (!nativeTextarea) return; if (!nativeTextarea) return;
@ -203,35 +199,36 @@ const handleCompositionUpdate = () => {
} }
} }
:deep(.ant-input-textarea) { :deep(.arco-textarea-wrapper) {
@include textarea-style; @include textarea-style;
.ant-input {
.arco-textarea {
padding: 0; padding: 0;
overflow: hidden; overflow: hidden;
position: absolute; position: absolute;
z-index: 1; z-index: 1;
width: 100%; width: 100%;
height: 100%;
background: transparent; background: transparent;
color: transparent; color: transparent;
caret-color: #211f24 !important; caret-color: #211f24 !important;
resize: none; resize: none;
@include textarea-padding; @include textarea-padding;
overflow-y: auto; overflow-y: auto;
border: none; }
.arco-textarea-word-limit {
z-index: 2;
}
&.arco-textarea-disabled {
.arco-textarea {
background: #f2f3f5;
}
} }
} }
:deep(.ant-input-data-count) {
z-index: 2;
}
&:deep(.ant-input:disabled) {
background: #f2f3f5;
}
// 处于中文输入法合成态时,显示真实文本并隐藏高亮层 // 处于中文输入法合成态时,显示真实文本并隐藏高亮层
:deep(.textarea-input.composing .ant-input) { :deep(.textarea-input.composing .arco-textarea) {
color: #211f24 !important; color: #211f24 !important;
-webkit-text-fill-color: #211f24 !important; -webkit-text-fill-color: #211f24 !important;
} }

View File

@ -1,12 +1,12 @@
<template> <template>
<div class="highlight-textarea-container"> <div class="highlight-textarea-container">
<TextArea <a-textarea
ref="textareaWrapRef" ref="textareaWrapRef"
v-model:value="inputValue" v-model="inputValue"
placeholder="请输入作品描述" placeholder="请输入作品描述"
:disabled="disabled" :disabled="disabled"
showCount show-word-limit
:maxlength="1000" :max-length="1000"
size="large" size="large"
class="textarea-input h-full w-full" class="textarea-input h-full w-full"
@input="handleInput" @input="handleInput"
@ -25,7 +25,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Input } from 'ant-design-vue'; import { Input } from 'ant-design-vue';
const { TextArea } = Input; const {TextArea} = Input
import { ref, computed, watch, defineProps, defineEmits, onMounted, onUnmounted } from 'vue'; import { ref, computed, watch, defineProps, defineEmits, onMounted, onUnmounted } from 'vue';
import { escapeRegExp } from './constants'; import { escapeRegExp } from './constants';
@ -52,6 +52,7 @@ const emit = defineEmits<{
// 内部状态管理 // 内部状态管理
const inputValue = ref(props.modelValue || ''); const inputValue = ref(props.modelValue || '');
const scrollTop = ref(0);
const focus = ref(false); const focus = ref(false);
const textareaWrapRef = ref(); const textareaWrapRef = ref();
let nativeTextarea: HTMLTextAreaElement | null = null; let nativeTextarea: HTMLTextAreaElement | null = null;
@ -114,8 +115,8 @@ const generateHighlightedHtml = (): string => {
onMounted(() => { onMounted(() => {
nativeTextarea = nativeTextarea =
(textareaWrapRef.value?.$el || textareaWrapRef.value)?.querySelector?.('textarea.ant-input') || (textareaWrapRef.value?.$el || textareaWrapRef.value)?.querySelector?.('textarea.arco-textarea') ||
document.querySelector('.textarea-input .ant-input'); document.querySelector('.textarea-input .arco-textarea');
if (nativeTextarea) { if (nativeTextarea) {
nativeTextarea.addEventListener('scroll', handleTextareaScroll); nativeTextarea.addEventListener('scroll', handleTextareaScroll);
@ -198,31 +199,36 @@ const handleCompositionUpdate = () => {
} }
} }
:deep(.ant-input) { :deep(.arco-textarea-wrapper) {
@include textarea-style; @include textarea-style;
padding: 0;
overflow: hidden;
position: absolute;
z-index: 1;
width: 100%;
background: transparent;
color: transparent;
caret-color: #211f24 !important;
resize: none;
@include textarea-padding;
overflow-y: auto;
}
:deep(.ant-input-data-count) { .arco-textarea {
z-index: 2; padding: 0;
} overflow: hidden;
position: absolute;
z-index: 1;
width: 100%;
background: transparent;
color: transparent;
caret-color: #211f24 !important;
resize: none;
@include textarea-padding;
overflow-y: auto;
}
&:deep(.ant-input:disabled) { .arco-textarea-word-limit {
background: #f2f3f5; z-index: 2;
}
&.arco-textarea-disabled {
.arco-textarea {
background: #f2f3f5;
}
}
} }
// 处于中文输入法合成态时,显示真实文本并隐藏高亮层 // 处于中文输入法合成态时,显示真实文本并隐藏高亮层
:deep(.textarea-input.composing .ant-input) { :deep(.textarea-input.composing .arco-textarea) {
color: #211f24 !important; color: #211f24 !important;
-webkit-text-fill-color: #211f24 !important; -webkit-text-fill-color: #211f24 !important;
} }