针对im输入框的一种处理方式

<template>
<div class="chatInput">
<!-- 通过contenteditable使普通的div变成富文本模式
由于要实现富文本的本地实时搜索,富文本没有change事件,而只能借用compositionstart,compositionend,input三个事件组合模拟出change
compositionstart:当用户使用拼音输入法开始输入拼音时触发,在键入之前只会触发一次(因此此方法可以判断用户是否在使用拼音输入法)
compositionend:中文输入完成时触发
input:输入什么都会触发
设置一个变量doing,初始值为false,compositionstart触发将doing值为true,拼音输入完成触发compositionend,此时将doing置为false,开始搜索,input只有在doing为false时触发,即表示此时未使用拼音,直接搜索-->
<div
id="edit"
ref="edit"
contenteditable
@compositionstart="doing = true"
@compositionend="handleSearch"
@input="handleKey"
@keyup="carReply"
@paste.prevent.trim="paste"
>
{{ splitContent.trim() }}
</div>
<div class="btn_wrap flex-end">
按Ctrl+Enter换行,按Enter输出
<el-button @click="send" type="primary"> 发送</el-button>
</div>
</div>
</template> <script setup lang="ts" name="chatInput">
import { ref, onMounted } from "vue";
import { httpRequest } from "../chatUtil";
import { fileUpload } from "@/api/modules/chat"; interface PropsInterface {
send: any;
}
const props = defineProps<PropsInterface>();
const doing = ref(false); const edit = ref() as any; // 这两属性都是控制输入框输入拆分的
let splitContent = "";
// 鼠标光标值
let lastEditRange = null as any; onMounted(() => {
// 初始化输入框聚焦,设置初始的选定对象节点
const editDom = document.querySelector("#edit") as any;
// 在失去焦点前保留上一次的选定对象节点
editDom.addEventListener("blur", (e: any) => setSection());
editDom.focus();
setSection();
});
const setSection = () => {
// 获取选定对象
let selection = getSelection() as any;
if (selection.getRangeAt && selection.rangeCount) {
// 设置最后光标对象
lastEditRange = selection.getRangeAt(0);
}
}; const handleSearch = () => {
doing.value = false;
// 此时搜索
};
const handleKey = () => {
const e = window.event as any;
if (!doing.value) {
// 此时搜索
}
};
// 按键控制输出
const carReply = () => {
const e = window.event as any;
// ctrl+enter实现换行,实测只有通过execCommened的方式插入换行符才可以实现换行
if (e.ctrlKey && e.keyCode == 13) {
document.execCommand("insertText", false, "\n");
} else if (e.keyCode == 13) {
send();
}
}; // 文本框粘贴
const paste = (e: any) => {
// 获取粘贴板数据
const clipdata = e.clipboardData || (window as any).clipboardData;
const files = clipdata.files;
const text = clipdata.getData("text/plain"); // 将文本按照html的格式粘贴进输入框中
text && document.execCommand("insertHTML", false, text);
if (files.length) {
Array.from(files).forEach((file: any) => {
// 只针对图片进行粘贴
if (file.type.match(/^image\//)) {
const windowURL = window.URL || window.webkitURL;
// 将file生成一个blob链接,可用于本地直接打开,也可以用于下载
const url = windowURL.createObjectURL(file);
document.execCommand("insertImage", true, url);
}
});
}
}; const send = () => {
const edit = document.querySelector("#edit") as any; if (edit.childNodes.length == 0) {
// 内容为空,给个提示阻止了
return;
} const _arr = Array.from(edit.childNodes) as any; // 递归遍历文本框内容,取dom元素的最深一级(实测发现富文本的html结构很乱,取到最深一层才能拿到内容)
contentRevese(_arr);
splitContent && props.send(splitContent);
// 输出后清空
splitContent = "";
edit.textContent = "";
}; const contentRevese: any = async (_arr: any) => {
for (let i = 0; i < _arr.length; i++) {
// 拿最深层
if (_arr[i].childNodes.length > 0) {
contentRevese(Array.from(_arr[i].childNodes));
} else {
if (_arr[i].tagName == "IMG") {
// 在取文本内容时,多行的文本应同时取,不能像图片一样,取到了就直接发送
props.send(splitContent);
splitContent = "";
// blob路径转file
let img = (await httpRequest(_arr[i].src)) as any; // 该blob对象用完后,应及时回收资源,节省内存
const windowURL = window.URL || window.webkitURL;
windowURL.revokeObjectURL(_arr[i].src);
const formData = new FormData() as any;
formData.append("files", img);
formData.append("type", "3");
const { data } = (await fileUpload(formData)) as any;
props.send(`img[${data.url}][${data.file_name}][size:${data.size}]`);
} else {
// 匹配下一段文本加换行
splitContent += _arr[i].textContent + "\n";
}
}
}
};
</script>

针对im输入框的一种处理方式的更多相关文章

  1. spring笔记--依赖注入之针对不同类型变量的几种注入方式

    控制反转和依赖注入讲的都是一个概念,只不过是站在了不同的角度,所谓的依赖注入: 是指在运行期,由外部容器动态地将依赖对象注入到组件中.当spring容器启动后,spring容器初始化,创建并管理bea ...

  2. IndexFlatL2、IndexIVFFlat、IndexIVFPQ三种索引方式示例

    上文针对Faiss安装和一些原理做了简单说明,本文针对标题所列三种索引方式进行编码验证. 首先生成数据集,这里采用100万条数据,每条50维,生成数据做本地化保存,代码如下: import numpy ...

  3. 巨蟒python全栈开发数据库前端6:事件onclick的两种绑定方式&&onblur和onfocus事件&&window.onload解释&&小米商城讲解

    1.回顾上节内容(JavaScript) 一.JavaScript概述 1.ECMAScript和JavaScript的关系 2.ECMAScript的历史 3.JavaScript是一门前后端都可以 ...

  4. 多对多三种创建方式、forms组件、cookies与session

    多对多三种创建方式.forms组件.cookies与session 一.多对多三种创建方式 1.全自动 # 优势:不需要你手动创建第三张表 # 不足:由于第三张表不是你手动创建的,也就意味着第三张表字 ...

  5. 多对多的三种创建方式-forms相关组件-钩子函数-cookie与session

    多对多的三种创建方式 1.全自动(推荐使用的**) 优势:第三张可以任意的扩展字段 缺点:ORM查询不方便,如果后续字段增加更改时不便添加修改 manyToManyField创建的第三张表属于虚拟的, ...

  6. Web APi之认证(Authentication)两种实现方式【二】(十三)

    前言 上一节我们详细讲解了认证及其基本信息,这一节我们通过两种不同方式来实现认证,并且分析如何合理的利用这两种方式,文中涉及到的基础知识,请参看上一篇文中,就不再叙述废话. 序言 对于所谓的认证说到底 ...

  7. CSS垂直居中的11种实现方式

    今天是邓呆呆球衣退役的日子,在这个颇具纪念意义的日子里我写下自己的第一篇博客,还望前辈们多多提携,多多指教! 接下来,就进入正文,来说说关于垂直居中的事.(以下这11种垂直居中的实现方式均为笔者在日常 ...

  8. Android开发之基本控件和详解四种布局方式

    Android中的控件的使用方式和iOS中控件的使用方式基本相同,都是事件驱动.给控件添加事件也有接口回调和委托代理的方式.今天这篇博客就总结一下Android中常用的基本控件以及布局方式.说到布局方 ...

  9. Web负载均衡的几种实现方式

    Web负载均衡的几种实现方式摘要:负载均衡(Load Balance)是集群技术(Cluster)的一种应用.负载均衡可以将工作任务分摊到多个处理单元,从而提高并发处理能力.目前最常见的负载均衡应用是 ...

  10. http协议(三)几种数据传输方式

    说说http协议的一些特点: 1)无状态 http协议是一种自身不对请求和响应之间的通信状态进行保存的协议,即无状态协议. 这种设置的好处是:更快的处理更多的请求事务,确保协议的可伸缩性 不过随着we ...

随机推荐

  1. bzoj 4195

    并查集水题 离散化之后直接并查集合并,在不等时判断两者是否在同一个集合內即可 注意排序 贴代码: #include <cstdio> #include <cmath> #inc ...

  2. 1903021126 申文骏 Java 第三周作业 编写代码及运行

    项目 内容 课程班级博客链接 19级信计班(本) 作业要求链接 第三周作业要求 博客名称 1903021126 申文骏 Java 第三周作业 编写代码及运行 要求 每道题要有题目,代码(使用插入代码, ...

  3. 前端本地 Nginx 反向代理

    一.问题引入 本地开发遇到线上bug,debug得stash代码切换分支,同时需切换开发环境与生产环境服务,npm run serve 或 npm start 费时 二.webpack-dev-ser ...

  4. Vue中nextTick的时序问题

    前言 Vue.$nextTick这个API相信很多人都用过,按照文档的解释,"在下次DOM更新循环结束之后执行延迟回调.在修改数据之后立即使用这个方法,获取更新后的DOM".我们通 ...

  5. 当前SAT主要关键技术及其相关文献2022-11-1

    摘录自: Tasniem Nasser Al-Yahya, Mohamed El Bachir Menai, Hassan Mathkour:Boosting the Performance of C ...

  6. FII-PRA006/010开发板硬件实验一

    FII-PRA006/010开发板硬件实验一 以一位全加器为例介绍如何利用开发板进行板载实验.一位全加器的Verilog代码如下: 1 2 3 4 5 6 7 8 9 10 module fadd1 ...

  7. 《JavaScript高级程序设计》Chapter03 JavaScript语言基础

    目录 Syntax Variable var let const Data Type Undefined Null Boolean Number String Symbol Object Operat ...

  8. ES2015常用知识点

    ES2015(又称ES6)部分1 let/const以及块作用域:2 循环语句 const arr=[1,2,3]; for(const item of arr){ console.log(item) ...

  9. heimaJava17

    java IO流 缓冲流 概念 缓存流也称为高效流.或者高级流.之前学习的字节流也可以称为原始流 作用:缓冲流自带缓冲区.可以提高原始字节流.字符流读写数据的性能 分类 字节缓冲流 字节缓冲输入流:B ...

  10. 实验5 开源控制器实践——POX

    实验5 开源控制器实践--POX 一.实验目的 1.能够理解 POX 控制器的工作原理: 2.通过验证POX的forwarding.hub和forwarding.l2_learning模块,初步掌握P ...