加入收藏 | 设为首页 | 会员中心 | 我要投稿 辽源站长网 (https://www.0437zz.com/)- 云专线、云连接、智能数据、边缘计算、数据安全!
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

Web聊天工具的富文本输入框

发布时间:2019-03-18 11:54:17 所属栏目:优化 来源:Jrain-前端玩具盆
导读:最近折腾 Websocket,打算开发一个聊天室应用练练手。在应用开发的过程中发现可以插入 emoji ,粘贴图片的富文本输入框其实蕴含着许多有趣的知识,于是便打算记录下来和大家分享。 仓库地址:chat-input-box 预览地址:https://codepen.io/jrainlau/p...
副标题[/!--empirenews.page--]

最近折腾 Websocket,打算开发一个聊天室应用练练手。在应用开发的过程中发现可以插入 emoji ,粘贴图片的富文本输入框其实蕴含着许多有趣的知识,于是便打算记录下来和大家分享。

仓库地址:chat-input-box

预览地址:https://codepen.io/jrainlau/p...

首先来看看 demo 效果:

是不是觉得很神奇?接下来我会一步步讲解这里面的功能都是如何实现的。

输入框富文本化

传统的输入框都是使用 <textarea> 来制作的,它的优势是非常简单,但最大的缺陷却是无法展示图片。为了能够让输入框能够展示图片(富文本化),我们可以采用设置了 contenteditable="true" 属性的 <div> 来实现这里面的功能。

简单创建一个 index.html 文件,然后写入如下内容:

  1. <div class="editor" contenteditable="true">  
  2.   <img src="https://static.easyicon.net/preview/121/1214124.gif" alt="">  
  3. </div> 

打开浏览器,就能看到一个默认已经带了一张图片的输入框:

Web聊天工具的富文本输入框

光标可以在图片前后移动,同时也可以输入内容,甚至通过退格键删除这张图片——换句话说,图片也是可编辑内容的一部分,也意味着输入框的富文本化已经体现出来了。

接下来的任务,就是思考如何直接通过 control + v 把图片粘贴进去了。

处理粘贴事件

任何通过“复制”或者 control + c 所复制的内容(包括屏幕截图)都会储存在剪贴板,在粘贴的时候可以在输入框的 onpaste 事件里面监听到。

  1. <div class="editor" contenteditable="true">  
  2.   <img src="https://static.easyicon.net/preview/121/1214124.gif" alt="">  
  3. </div> 

而剪贴板的的内容则存放在 DataTransferItemList 对象中,可以通过 e.clipboardData.items 访问到:

细心的读者会发现,如果直接在控制台点开 DataTransferItemList 前的小箭头,会发现对象的 length 属性为0。说好的剪贴板内容呢?其实这是 Chrome 调试的一个小坑。在开发者工具里面,console.log 出来的对象是一个引用,会随着原始数据的改变而改变。由于剪贴板的数据已经被“粘贴”进输入框了,,所以展开小箭头以后看到的 DataTransferItemList 就变成空的了。为此,我们可以改用 console.table 来展示实时的结果。

在明白了剪贴板数据的存放位置以后,就可以编写代码来处理它们了。由于我们的富文本输入框比较简单,所以只需要处理两类数据即可,其一是普通的文本类型数据,包括 emoji 表情;其二则是图片类型数据。

新建 paste.js 文件:

  1. const onPaste = (e) => {  
  2.   // 如果剪贴板没有数据则直接返回  
  3.   if (!(e.clipboardData && e.clipboardData.items)) {  
  4.     return  
  5.   }  
  6.   // 用Promise封装便于将来使用  
  7.   return new Promise((resolve, reject) => {  
  8.     // 复制的内容在剪贴板里位置不确定,所以通过遍历来保证数据准确  
  9.     for (let i = 0, len = e.clipboardData.items.length; i < len; i++) {  
  10.       const item = e.clipboardData.items[i]  
  11.       // 文本格式内容处理  
  12.       if (item.kind === 'string') {  
  13.         item.getAsString((str) => {  
  14.           resolve(str)  
  15.         })  
  16.       // 图片格式内容处理  
  17.       } else if (item.kind === 'file') {  
  18.         const pasteFile = item.getAsFile()  
  19.         // 处理pasteFile  
  20.         // TODO(pasteFile)  
  21.       } else {  
  22.         reject(new Error('Not allow to paste this type!'))  
  23.       }  
  24.     }  
  25.   })  
  26. }  
  27. export default onPaste 

(编辑:辽源站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读