前言
大家肯定对@功能不陌生,在如今的各大社交软件中它是一种不可或缺的功能。实现@人的功能并不复杂,只需将@人员的id传给后端,后端下发通知即可。主要的复杂点在于一键删除功能与变色功能,web端可以使用现成库caret.js或者 At.js 来实现。但笔者需要在小程序中实现这个功能,而且在textarea标签里实现,当然@人名的变色功能自然而然就砍掉了。
准备工作
怎么来实现一键删除呢?首先想到对@人名前后用特殊符号标记+正则来实现,但结果不是很理想,扩展性也比较差,如果还要匹配话题之类的就得多写一套代码,所以就试着找其他方法解决。发现wx.getSelectedTextRange可以获取文本框聚焦时的光标,这样就可以将@人员插入文本指定位置。文本框事件 @input 的可以获取到变化的数据与位置,那就可以根据变化的位置与变化的数据来判断是否命中@人员,@人员的位置可以通过计算获取。
// bindinput事件返回值
// value为变化后的值 cursor为变化的位置 keyCode为触发的键值
const {value, cursor, keyCode} = event.detail
// 获取光标位置,聚焦时生效
wx.getSelectedTextRange({
complete: res => {
console.log('光标位置:', res.start, res.end)
}
})
准备工作做好了就进入实践环节,毕竟实践是检验真理的唯一标准。设计图呈现:通过点击@按钮到人员列表页面,选择人员后返回,具体如下图。这里涉及页面之间的通信问题,可以通过状态管理器、数据缓存、获取页面栈设置数据等来实现,本例中使用数据缓存。
数据组装
从人员列表返回用wx.navigateBack,会触发 onShow 这个生命周期,所以需要在 onShow 里组装@数据。获取到的@人员根据光标位置对文本进行字符串截取组装,若未获取到光标位置则直接将@人员添加到文本末尾。然后对@人员数据、文本数据等进行备份,用于后续的计算。
initAtFn() {
// 获取@人员数据
const me = this
const initMemberList = wx.getStorageSync('atMemberList')
const atMemberArr = initMemberList ? initMemberList : []
// 赋值后清除@人员数据
wx.removeStorageSync('atMemberList')
// 获取上一次光标的位置
const preCursor = wx.getStorageSync('blurCursor') ? parseInt(wx.getStorageSync('blurCursor')) : me.content.length
// 将 @人员数据 并入内容区域
if (atMemberArr.length > 0) {
// 获取人员名称
const atMemberName = `@