【实战】我是如何在输入框实现@ At功能的
【实战】我是如何在输入框实现 @ At 功能的
InfinityTomorrow 程序员成长指北;)
程序员成长指北
微信号 coder_growth
功能介绍 专注 Node.js 技术栈分享,从 前端 到 Node.js 再到 后端数据库,祝您成为优秀的高级 Node.js 全栈工程师。一个有趣的且乐于分享的人。座右铭:今天未完成的,明天更不会完成。
2021-12-21 08:47
收录于话题
程序员成长指北
专注 Node.js 技术栈分享,从 前端 到 Node.js 再到 后端数据库,祝您成为优秀的高级 Node.js 全栈工程师。一个有趣的且乐于分享的人。座右铭:今天未完成的,明天更不会完成。
94 篇原创内容
公众号
大厂技术高级前端 Node 进阶
=================
点击上方 程序员成长指北,关注公众号
回复 1,加入高级 Node 交流群
作者:InfinityTomorrow 授权转载
一、前言
最近接手了一个需求,在评论框中实现 @At 通知用户的功能。这个可以说是我的知识盲点了,但是其实很多应用都有这类功能了,例如:QQ 空间、微博搜索、企业微信的 TAPD… 但是一看就不想不做~😭(产品经理 ps:为什么别人可以做你不可以做?)
明确目标
二、技术方案分析
在寻求我们的技术方案的时候、我们首先要明确我们想要的功能是什么
你知道自己想要什么,知道要去哪儿、当我们把需求、功能、拆解的很细的时候可以节约我们走弯路的时间 (ps: 不要问我怎么知道的)
当前需求的拆解
- 按住
shift + @
的时候,弹出通知列表 - 选择时
@
的用户标签插入当前的光标位置中 - 生成
@
的用户标签的规则是:高亮、携带用户 ID、一键删除信息、不可以编辑。 - 文本框要随内容自适应高度
Android
、IOS
、Web
显示多端一致。- 具有扩张性,未来评论可能插入图片文件等….
市面流行方案对比
ps: 方案有很多种方式,适合自己、适合团队的才是最佳实践。没有完美的方案 (ps: 只有不听话的产品经理🙂🙂🙂) 的产品经理🙂🙂🙂)
textarea
、input
(例:新浪微博)流程大概都是 (监听 keyup, 获取光标位置拆入 @的节点…), 但是… 相信我如果你手写,你不会快乐的!!!所以推荐下面的库给大家、只要稍作改动就可以使用啦~~
Tribute.js(推荐, ES6)
At.js JQ)
contenteditable (例:QQ 空间, 掘金)
HTML5 新属性规定元素内容是否可编辑、可以做为编辑器使用,由于时间原因并没有深入体会、感兴趣的小伙伴可以看一下以下内容
contenteditable-MDN
contenteditable 实现编辑器, 光标、输入法处理
基于 contenteditable 技术实现 @选人功能
富文本 (例:企业微信 TAPD)
支持 文本、富文本、图片、拥有丰富的配置与强大的 API。
因为考虑到扩展性与踩坑的深浅、api 的丰富程度最终选择 wangeditor 富文本 做为最终的方案。
既然选择好了方向,那就开冲吧、冲冲冲!!!
三、准备工作
本功能是基于wangeditor
富文本编辑器来实现的,本文wangeditor
版本 4.3.0
npm i wangeditor --save
初始化一下项项目结构~
<template> <div ref="editor"></div></template><script>import E from 'wangeditor'export default { data() { return { editor: '' } }, mounted() { this.initEditor() // 初始化编辑器 }, methods: { initEditor() { let editor = new E(this.$refs.editor) editor.config.placeholder = '写评论~可手动输入@通知其他人' editor.config.menus = [] // 显示菜单按钮 editor.config.showFullScreen = false // 不显示全屏按钮 editor.config.pasteIgnoreImg = true // 如果复制的内容有图片又有文字,则只粘贴文字,不粘贴图片。 editor.config.height = '100' editor.config.focus = false // 取消自动 focus editor.create() this.editor = editor // 销毁编辑器,定义与销毁应该在同一个地方,增加阅读性,方便后期维护。 this.$once('hook:beforeDestroy', () => { this.editor.destroy() this.editor = null }) } }}</script>
拓展知识:
- 为什么在上文中使用 ”new E(this.$refs.editor)“ 使用 ref 的方式而不是 ID 的方式呢?
- 使用 ref 的好处是具有良好的可重用性和范围。因为 ref 只留在这个组件中,所以当您操作这个 ref 时,它不会干扰其他组件。
- 如果您使用 id,它就有重复的问题,这就意味着你不可能重用某个元素。
- 例:我再生成一个富文本组件就会初始化失败、因为 id 是唯一的。这就是为什么很多人推荐尽量少用 ID 的原因。(不要问我为什么知道这个问题!!!)。
- wangeditor 的配置只支持固定高度,如果我们想支持文本框最小高度、文字随内容到最大高度 xx 时自适应滑动怎么做呢? editor.config.height = ‘100’ ::v-deep .w-e-text-container { min-height: 100px; max-height: 300px; height: auto !important; border: 1px solid #dbdbdb !important; border-radius: 4px; overflow-y: auto;}
四、@的功能的实现
按住shift + @
的时候,弹出通知人列表
- 通过 $event 可以获取键盘的 keyCode 达到监听的目的
- e.preventDefault 可以阻止我输入的 @字符的默认事件
- getSelection 可以获取光标的位置、给插入标签一个坐标。
- 要兼容中文输入法的时候 @的事件判断 (如:中文输入法打 “哈哈哈 @” 这个时候不能监听 @的事件 )
- 中文输入法的时候单独输入 @的时
怎么判断中文输入?
当用户使用中文输入法开始输入中文时,compositionstart
事件就会被触发。当文中文输入完成或取消时, compositionend
事件将被触发。利用这个机制我们就可以判断是否中文状态了
positionstart
事件, 当用户使用拼音输入法开始输入汉字时,这个事件就会被触发。compositionend
事件, 当文中文输入完成时, compositionend 事件将被触发。