基于vue2.x + vant2.x 实现的仿微信@功能(稍作修改即可支持原生js和react),兼容pc端和手机端,如有bug,欢迎提出~
年后分配到一个新项目 - 企业微信论坛。项目涉及到发帖子、评论、留言等功能,刚好和我的个人博客功能类似,不能说一模一样吧,也八九不离十了(内心偷乐😁😁)。
但是,令人头疼的问题来了,附加了一个@功能
,即在评论框中输入@
实现通知用户的功能。这个可以说触及到我的的知识盲点了,但其实很多应用都有这类功能了,如:微博、QQ、微信、企业微信… 哎,需求需要,不得不做,静下心来好好研究研究叭~
方案很多,适合自己、适合团队才称得上完美。
这里归纳了几种常用的方案:
wangeditor
,前一天在Issues
提出@功能需求,隔天就做出了一版@功能的插件,可惜我已经用前者实现了👽👽)
二、效果和功能描述
最终目标:实现仿微信@用户功能。
demo地址: zugelu - 仿微信@功能
1. 效果图 2. 主要功能 在输入框内任何地方输入@
,或点击@按钮
(demo中Show @ Menu
按钮),d出选择用户d框人员d框支持搜索功能、支持异步选择人员,在光标后追加@名称
,并绑定人员相关数据@名称
作为整体,光标不可游走其中删除时,将@名称
作为一个整体进行删除
实现以上功能,可以说已经完成了一个高仿微信@功能。
三、准备工作本案例是基于vue-quill-editor富文本编辑器(v3.0.6)和quill-mention(v3.1.0)来实现的。需下载quill相关依赖。
npm i vue-quill-editor quill-mmention --save
初始化项目结构
<template>
<div id="at">
<quill-editor
ref="myQuillEditor"
v-model="content"
:options="editorOption"
/>
<div id="toolbar">div>
div>
template>
<script>
import { quillEditor } from 'vue-quill-editor'
import 'quill/dist/quill.snow.css'
import 'quill-mention'
export default {
name: 'at-mention',
components: {
quillEditor
},
data () {
return {
content: '', // 富文本html
isClickMention: false, // 是否点击@按钮打开@菜单d框
isChineseInputMethod: false, // 是否中文输入法状态
show: false, // d框显示状态
editorOption: {
placeholder: '说点什么呢。。。',
modules: {
toolbar: { // 自定义toolbar,本案例隐藏
container: '#toolbar',
},
mention: { // 将 quill-mention 配置传递给 quill
mentionDenotationChars: ["@"], // 指定哪些字符可以触发@提及
source: function (searchTerm, renderList, mentionChar) { // @提及回调
console.log(searchTerm, renderList, mentionChar)
renderList([], searchTerm) // 因为我们要自定义d框,所以这里把默认的@用户数据置空
}
}
}
}
}
},
computed: {
editor () {
return this.$refs.myQuillEditor.quill
}
},
}
script>
<style >
/* quill-toolbar */
.ql-toolbar {
padding: 0 !important;
border: 0 !important;
}
style>
初始化完成,就可以使用基于quill-mention
实现的@
功能了,但现有功能并不能满足我的需求(@之后从底部d出用户列表),需要在现有基础上进行改造升级。
提示:
mention -> source 中,renderList([], searchTerm)
, 因为我们要自定义d框,所以这里把默认的@用户数据置空。css样式中.ql-toolbar
,去除默认边距,目的隐藏toolbar
后续data
所用到的数据,在初始化阶段已全部列出
四、实现步骤
1. 中文输入法的判断
中文模式下输入@要进行判断,如:输入“说点什么呢@”,这个时候不能监听@事件。
如何判断中文输入?
当用户使用中文输入法开始输入中文时,compositionstart
事件就会被触发。当文中文输入完成或取消时,compositionend
事件将被触发。利用这个机制我们就可以判断是否中文状态。
<template>
<div id="at">
<quill-editor
v-model="content"
@compositionstart.native="onCompositionstart"
@compositionend.native="onCompositionend"
/>
div>
template>
<script>
export default {
data () {
return {
isChineseInputMethod: false, // 是否中文输入法状态
}
},
methods: {
// 中文输入触发
onCompositionstart () {
this.isChineseInputMethod = true
},
// 中文输入关闭
onCompositionend () {
this.isChineseInputMethod = false
}
...
}
}
script>
2. @事件的监听
判断设备类型(适配电脑和手机端)
// 判断设备是否为 Mobile (提示:请勿在浏览器调试模式下,切换手机模式,否则会导致@功能失效)
isMobile () {
return navigator.userAgent.match(/(iPhone|iPod|Android|ios|iOS|iPad|Backerry|WebOS|Symbian|Windows Phone|Phone)/i)
},
根据终端判断用户是否输入@符号
// 判断是否输入 @符号
isAtCode (e) {
return this.isMobile() ?
((e.keyCode === 229 || e.keyCode === 50) && e.code === 'Digit2' && e.key === '@')
: (((e.keyCode === 50 && e.key === '@') || (e.keyCode === 229 && e.code === 'Digit2')) && e.shiftKey)
}
监听富文本keydown事件,判断是否为非中文状态下键入的@符号,如是,则打开用户列表d框
// 键盘按下
onKeyDown (e) {
// 判断状态非中文输入法,并且监听到了@的事件
if (!this.isChineseInputMethod && this.isAtCode(e)) {
// 输入@打开@菜单d框
this.show = true
}
},
PS:本案例用户列表的代码就不贴了,可根据需求自定义,或前往at-mention获取demo代码。
3. 点击用户生成@标签使用quill-mention
提供的API - insertItem
来实现。
当点击@列表中的想要@的用户,则触发selectItem
事件,把@的内容插入到对应位置。
// 选择要@的用户
selectItem (item) {
this.insertItem(item)
this.show = false
},
// 插入@内容,item即为用户信息
insertItem (item) {
const mention = this.editor.getModule('mention')
mention.insertItem({ id: item.id, value: item.name, denotationChar: '@' }, true)
}
这样会有一个问题,@用户的时候多了一个@符号,原因是insertItem
会默认帮我们添加一个@符号,加上手动输入的@符号就多出一个@。
所以这里需要特殊处理一下,调用history.undo()
撤销API(需要额外配置下history
参数):
editorOption: {
modules: {
...
history: { // history 配置(History模块负责处理Quill的撤销和重做)
delay: 0 // 将延迟设置为0,那么几乎每次输入字符都会被记录成一个变化,然后,撤销动作就会一次撤销一个字符
}
}
},
// 选择要@的用户
selectItem (item) {
// 如果不是通过@按钮打开的d框,则需要删除多余的@符号
if (!this.isClickMention) {
// 撤销一步,删除手动输入的@符号(需在modules中配置history: { delay: 0 })
this.undo()
}
this.insertItem(item)
this.show = false
},
// 撤销
undo () {
this.editor.history.undo();
},
4. 点击外部的@按钮插入@标签
非常简单,直接调用API - insertItem
来插入@标签即可。(会默认添加@符号)
这个功能我自己测试没问题,兼容性也不错(并未进行详细测试、可能会存在其他问题),如果使用中遇到问题,欢迎提出反馈,希望能和大家一起进步~
本文首发于足各路的博客,后续会同步更新到掘金、知乎、CSDN。关注足各路、前端不迷路!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)