实现div 变成输入框并可复制图片进来
问题描述:
需要做一个类似聊天的输入框,可以复制文字,复制图片

解决方案:
div 设置属性 contenteditable 以及复制粘贴设置 @paste="handlePaste"
HTML 代码:
<div class="reply-box" v-if="isReply">
<div
class="reply-input beauty-scroll"
contenteditable
ref="editableDiv"
id="editBox"
row="3"
@paste="handlePaste"
@focus="onFocusEditableDiv"
@click="showImageModal"
></div>
<div class="reply-btm">
<!-- 必须使用button 按钮能够保持焦点在当前位置的原因是它是一个可聚焦的元素,并且浏览器默认会保留焦点在其上;只有一个图片,焦点会跑到最前面 -->
<a-button class="sendImg-btn">
<img src="../../../../assets/img/sendImg.png" alt="" class="sendImg" @click="selectImg">
</a-button>
<a-button class="reply-btn" type="primary" size="small" @click="sendMessage" :loading="loading">发送</a-button>
</div>
</div>
JS 代码 :
/**
* 粘贴图片
*/
async handlePaste(event) {
event.preventDefault(); // 阻止默认的粘贴行为
const clipboardData = event.clipboardData || window.clipboardData;
const types = clipboardData.types;
if (types.includes("text/plain")) {
try {
const clp = await navigator.clipboard.readText();
// 将纯文本插入到可编辑区域
this.insertPlainText(clp);
} catch (error) {
console.error("Failed to read clipboard contents: ", error);
}
}
if (types.includes("Files")) {
for (let index = 0; index < clipboardData?.files.length; index++) {
const file = clipboardData?.files[index];
const isXls = /\.(jpg|png|jpeg)$/.test(file.name.toLowerCase());
if (isXls) {
let options = {
file: file,
}
this.uploadImg(options)
}
}
}
},
//插入纯文本 document.execCommand 已被弃用 换成这种方式
insertPlainText(text) {
const selection = window.getSelection();
if (selection.getRangeAt && selection.rangeCount) {
const range = selection.getRangeAt(0);
const doc = range.commonAncestorContainer.ownerDocument;
range.deleteContents();
const textNode = doc.createTextNode(text);
range.insertNode(textNode);
range.setStartAfter(textNode);
range.setEndAfter(textNode);
selection.removeAllRanges();
selection.addRange(range);
}
},
//插入图片
insertImageIntoFocusedDiv(url) {
const focusedElement = document.activeElement;
if (
focusedElement.tagName.toLowerCase() === "div" &&
focusedElement === this.$refs.editableDiv
) {
this.insertImage(focusedElement, url);
} else {
console.log("没有找到合适的可编辑 div");
}
},
insertImage(element, url) {
const selection = window.getSelection();
const range = selection.getRangeAt(0);
const imgElement = document.createElement("img");
imgElement.src = url;
imgElement.style.width = "100px";
imgElement.style.verticalAlign = "baseline";
imgElement.style.cursor = "zoom-in";
range.insertNode(imgElement);
// 更新光标位置
const newRange = document.createRange();
newRange.setStartAfter(imgElement);
newRange.collapse(true);
selection.removeAllRanges();
selection.addRange(newRange);
},
//选择图片
selectImg() {
this.$refs.editableDiv.focus(); // 确保焦点在可编辑的 div 上
document.querySelector(".avatar-uploader input").click();
},
// 上传前校验
async beforeUpload(file) {
const isXls = /\.(xls|jpg|png|jpeg)$/.test(file.name.toLowerCase());
const isLt20M = file.size / 1024 / 1024 < 20;
return new Promise((resolve) => {
if (!isXls) {
this.$message.error("请上传正确格式的文件!");
return false;
}
if (!isLt20M) {
this.$message.error("请上传小于20M的文件!");
return false;
}
resolve(true);
return true;
});
},
//图片上传之后
async uploadImg(options) {
let result = await this.uploadFile(options.file);
let protocol = window.location.protocol; //协议
let domain = window.location.hostname; // 域名
let port = window.location.port ? `:${window.location.port}` : ""; // 端口号
const URL = protocol + "//" + domain + port + "/aldApi" + result.filePath;
//这里拿到文件之后,可根据自己需求来进行文件处理,处理完之后,插入输入框
this.insertImageIntoFocusedDiv(URL);
},
点击发送,直接拿到div 输入框里面的html


浙公网安备 33010602011771号