1. 【实战】我是如何在输入框实现@ At功能的

【实战】我是如何在输入框实现 @ At 功能的

InfinityTomorrow 程序员成长指北;)

程序员成长指北

微信号 coder_growth

功能介绍 专注 Node.js 技术栈分享,从 前端 到 Node.js 再到 后端数据库,祝您成为优秀的高级 Node.js 全栈工程师。一个有趣的且乐于分享的人。座右铭:今天未完成的,明天更不会完成。

2021-12-21 08:47

收录于话题

【实战】如何在输入框实现@ At功能的 - 图1

程序员成长指北

专注 Node.js 技术栈分享,从 前端 到 Node.js 再到 后端数据库,祝您成为优秀的高级 Node.js 全栈工程师。一个有趣的且乐于分享的人。座右铭:今天未完成的,明天更不会完成。

94 篇原创内容

公众号

大厂技术高级前端 Node 进阶

=================

点击上方 程序员成长指北,关注公众号

回复 1,加入高级 Node 交流群

作者:InfinityTomorrow 授权转载

链接:https://juejin.cn/post/6982251438332182542

一、前言

最近接手了一个需求,在评论框中实现 @At 通知用户的功能。这个可以说是我的知识盲点了,但是其实很多应用都有这类功能了,例如:QQ 空间、微博搜索、企业微信的 TAPD… 但是一看就不想不做~😭(产品经理 ps:为什么别人可以做你不可以做?)

明确目标

【实战】如何在输入框实现@ At功能的 - 图2

二、技术方案分析

在寻求我们的技术方案的时候、我们首先要明确我们想要的功能是什么

你知道自己想要什么,知道要去哪儿、当我们把需求、功能、拆解的很细的时候可以节约我们走弯路的时间 (ps: 不要问我怎么知道的)

当前需求的拆解

  1. 按住shift + @ 的时候,弹出通知列表
  2. 选择时 @的用户标签插入当前的光标位置中
  3. 生成@的用户标签的规则是:高亮、携带用户 ID、一键删除信息、不可以编辑。
  4. 文本框要随内容自适应高度
  5. AndroidIOSWeb显示多端一致。
  6. 具有扩张性,未来评论可能插入图片文件等….

市面流行方案对比

ps: 方案有很多种方式,适合自己、适合团队的才是最佳实践。没有完美的方案 (ps: 只有不听话的产品经理🙂🙂🙂) 的产品经理🙂🙂🙂)

  • textareainput(例:新浪微博)

  • 流程大概都是 (监听 keyup, 获取光标位置拆入 @的节点…), 但是… 相信我如果你手写,你不会快乐的!!!所以推荐下面的库给大家、只要稍作改动就可以使用啦~~

  • Tribute.js(推荐, ES6)

  • At.js JQ)

  • contenteditable (例:QQ 空间, 掘金)

  • HTML5 新属性规定元素内容是否可编辑、可以做为编辑器使用,由于时间原因并没有深入体会、感兴趣的小伙伴可以看一下以下内容

  • contenteditable-MDN

  • contenteditable 实现编辑器, 光标、输入法处理

  • 基于 contenteditable 技术实现 @选人功能

  • 富文本 (例:企业微信 TAPD)

  • 支持 文本、富文本、图片、拥有丰富的配置与强大的 API。

  • 因为考虑到扩展性与踩坑的深浅、api 的丰富程度最终选择 wangeditor 富文本 做为最终的方案。

既然选择好了方向,那就开冲吧、冲冲冲!!!

三、准备工作

本功能是基于wangeditor富文本编辑器来实现的,本文wangeditor版本 4.3.0

  1. npm i wangeditor --save

初始化一下项项目结构~

  1. <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>

拓展知识:

  1. 为什么在上文中使用 ”new E(this.$refs.editor)“ 使用 ref 的方式而不是 ID 的方式呢?
  • 使用 ref 的好处是具有良好的可重用性和范围。因为 ref 只留在这个组件中,所以当您操作这个 ref 时,它不会干扰其他组件。
  • 如果您使用 id,它就有重复的问题,这就意味着你不可能重用某个元素。
  • 例:我再生成一个富文本组件就会初始化失败、因为 id 是唯一的。这就是为什么很多人推荐尽量少用 ID 的原因。(不要问我为什么知道这个问题!!!)。
  1. 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 事件将被触发。