针对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. postman收藏 -大佬玩法。

    请求顺序:    https://www.cnblogs.com/superhin/p/11454832.html 在Postman脚本中发送请求(pm.sendRequest) : https:// ...

  2. GraalVM & Spring Boot初体验

    前言 这两天封在家里,一直在琢磨想去把这个博客项目改成微服务的形式.不过就目前而言我的服务器内存放好几个Java进程是吃不消的,原因在于一个独立的JVM所占用的内存资源太吃内存.不过在云原生时代,使用 ...

  3. redis存储类型-数字和带双引号的数字

    这个是不一样的值,出现了转换异常

  4. SQL Server datetime类型为null的有趣实验

    @data1 --变量 测试用 @data2 --当前时间 当@data1为null 则格式转换错误 直接控制台什么也不显示 也不报错 当定义'' 显示默认时间

  5. 前端上传获取excel文件后,如何读取excel文件的内容

    1.安装xlsx npm install xlsx --save-dev 2.引入xlsx并封装读取excel方法 import * as XLSX from "xlsx"; /* ...

  6. vim实用用法

    1 dd 删除1行 1 gg 跳到第一行 G 文本最后 C 删除当前光标到行尾,并进入插入模式 D 删除当前光标到行尾 dw 删除一个单词 yw 复制一个单词 r /PATH/FROM/SOMEFIL ...

  7. C++11新特新-varitable template

    C++11新特新-varitable template应用 可变参模板原理可以仔细阅读C++primer 第5版相关部分 应用1 一个万用的HashFun 通过不断调用可变模板函数进行参数包的运算,最 ...

  8. Python生态工具

    Python内置小工具 1秒钟启动一个下载服务器 在实际工作中,时常会有这样的一个需求:将文件传给其他同事.将文件传给同事本身并不是一个很繁琐的工作,现在的聊天工具一般都支持文件传输.但是,如果需要传 ...

  9. 后端返回字符流,前端处理进行excel文件导出操作

    针对于这种的文件导出,最关键的是响应类型的设置,也就是responseType的设置(responseType:"arraybuffer"或者responseType:" ...

  10. 《Linux就该这么学》这本书写得真好,我很喜欢。

    本书是由全国多名红帽架构师(RHCA)基于最新Linux系统共同编写的高质量Linux技术自学教程,极其适合用于Linux技术入门教程或讲课辅助教材,目前是国内最值得去读的Linux教材,也是最有价值 ...