需求: #话题功能
预期
1、当我输入 #号紧跟着的文案要高亮
2、复制文案粘贴文案也要保持之前的状态,比如 复制 #文案#文案1,粘贴后也要 #文案#文案1
目前遇到的问题:
当我输入文案
光标会自动会跳到最前面,应该是使用了innerHTML的原因,所以光标默认移动到最前面。
我想要的是光标紧跟着文案,跟textarea一样
下面是代码 或点击此链接跳到sandbox
<script setup lang="ts">
import { ref, reactive, watch, watchEffect, onMounted } from "vue";
const editableDiv = ref<any>(null);
const formState = reactive<any>({
description: "",
});
// 触发描述框 input事件
const handleDescInput = () => {
const result = document.createElement("p");
const content = editableDiv.value.textContent;
if (!isComposing) {
for (let i = 0; i < content.length; i++) {
const char = content[i];
if (char === "#") {
let hashtag = char;
i++;
while (
i < content.length &&
content[i] !== " " &&
content[i] !== "#" &&
content[i] !== "\n"
) {
hashtag += content[i];
i++;
}
if (hashtag.length > 1) {
// 创建span元素并设置样式和内容
var span = document.createElement("span");
span.className = "hashtag";
span.innerText = hashtag;
console.log("hashtag", hashtag);
// 将span元素添加到可编辑div中
result.appendChild(span);
} else {
result.appendChild(document.createTextNode(char));
}
i--;
} else {
result.appendChild(document.createTextNode(char));
}
}
}
formState.description = result.innerHTML;
};
// 添加paste事件监听器,以便处理粘贴
const handleDescPaste = (e) => {
// 阻止默认粘贴行为
e.preventDefault();
// 获取粘贴的纯文本内容
var pastedText = (e.originalEvent || e).clipboardData.getData("text/plain");
// 在粘贴的文本中插入换行符
pastedText = pastedText.replace(/\s+/g, "\n");
// 将处理后的文本插入可编辑div
document.execCommand("insertText", false, pastedText);
};
let isComposing = false;
// 处理中文输入法的组合开始事件
const handleCompositionStart = () => {
console.log("正在组织...");
isComposing = true;
};
// 处理中文输入法的组合结束事件
const handleCompositionEnd = () => {
console.log("结束组织...");
isComposing = false;
handleDescInput();
};
</script>
<template>
<div
ref="editableDiv"
class="editableDiv"
contenteditable="true"
@input="handleDescInput"
@paste="handleDescPaste"
@compositionend="handleCompositionEnd"
@compositionstart="handleCompositionStart"
v-html="formState.description"
></div>
</template>
<style scoped>
.editableDiv {
border: 1px solid;
width: 1000px;
height: 60px;
border: 1px solid;
text-align: left;
caret-color: red;
}
</style>
<style>
.hashtag {
color: red !important;
}
</style>