需求分析
这个功能最让人头疼的地方在于小程序文本域的输入回调提供的信息过少,没办法直接判断输入位置,在 Taro 文档中提到 TextArea 的 onInput 事件会返回文本内容 value
、光标位置 cursor
、按键类型 keyCode
三个值。但是在我的实际测试中,只拿到了 value
。
这是什么人间疾苦。
所以说,我们需要先搞一个算法来找到当前新输入了什么以及在哪输入的。
之后的问题就好办了,如果输入的是 @,就拉起动作面板,选择某个人后触发回调,在正文里插入这个人的名字,然后把对应的信息存到另一个 state 方便后续操作就可以了。
组件实现
这里先贴出来完整代码,有需要的可以直接拿去用,组件库是 taro-vant
:
MentionTextarea\index.tsx
import { useReady } from "@tarojs/taro";
import { FC, forwardRef, useImperativeHandle, useRef, Ref, useState } from "react";
import { View, Textarea } from "@tarojs/components";
import { ActionSheet, Search, Cell, Notify } from "@antmjs/vantui";
import { debounce, DebouncedFunc } from 'lodash';
import { getQuestionUser } from "@/services/engineerCarbonCopyProblem";
export interface Props {
defaultContent?: string
className?: string
ref?: Ref<MentionTextareaRef>
}
/**
* 抄送问题人员
*/
export interface QuestionUser {
id: number
originId: number
name: string
tel: string
/**
* 岗位名
*/
type: string
}
export interface MentionTextareaRef {
/**
* 获取填写的内容
* @returns [正文内容,抄送人员列表]
*/
getContent: () => [string, QuestionUser[]]
/**
* 设置填写的内容
*/
setContent: (content: string) => void
}
/**
* 找到新旧字符串的变化
*
* @param oldStr 老字符串
* @param newStr 新字符串
* @returns [变更的字符(删除则为空), 变更的位置]
*/
const findDiffChar = (oldStr: string, newStr: string): [string, number] => {
const arr1 = oldStr.split("");
const arr2 = newStr.split("");
// 用较长的内容进行遍历
const