vue3 中组合键实现换行
需求背景
- 有一个聊天室功能,采用输入框的形式,输入完毕使用Enter,可以直接进行发送。使用一些组合键 比如 command+Enter / shift+Enter / alt + Enter … 可以实现换行操作。但现实的情况是,原生 Enter 天然支持换行,但是我们需要阻止掉。但是组合键又需要自己去实现换行
效果图
- 原生使用Enter 换行
- 实现自定义组合键换行效果图
实现过程分析
- 根据需求定义组合键 Map
- 换行是根据光标位置进行换行,所以首先要获取到光标的位置
- 根据光标的位置,拆分成两段文本
- 合并两端文本为带有换行符的新文本
- 重新设置光标位置
代码实现
- template模版
<el-input ref="editorRef" v-model="valueHtml" type="textarea" :rows="4" placeholder="请输入内容" @keydown="handleKeyDown" > </el-input>
js逻辑
import { ref, nextTick } from 'vue' const currentEvent = ref() const valueHtml = ref('') const editorRef = ref() const handleKeyDown = ($event: Event) => { const event = $event as KeyboardEvent currentEvent.value = event.target as HTMLInputElement // 定义组合键 Map const shortCutKeys: (keyof KeyboardEvent)[] = ['metaKey', 'altKey', 'ctrlKey', 'shiftKey'] const isEnterKey = event.key === 'Enter' const isShortcutKeys = shortCutKeys.some((item) => event[item]) if (isEnterKey && isShortcutKeys) { // 获取光标位置 const cursorPosition = currentEvent.value.selectionStart // 拆分成两段文本 const textBeforeCursor = valueHtml.value.slice(0, cursorPosition) const textAfterCursor = valueHtml.value.slice(cursorPosition) // 合并为带有换行符的新文本 const newText = textBeforeCursor + ' ' + textAfterCursor // 更新输入框的值 valueHtml.value = newText // 文本编辑器的高度发生变化后 nextTick(() => { // 高度变化 自动滚动到底部 const editor = editorRef.value.textarea editorRef.value.textarea.scrollTop = editor.scrollHeight // 设置光标位置为: start 和 end 相同,光标会移动到换行符后面的新行首 currentEvent.value.setSelectionRange(cursorPosition + 1, cursorPosition + 1) }) } else if (event.key === 'Enter') { // 阻止掉 Enter 的默认换行行为 event.preventDefault() // do yourself things for example send } }
细节优化
- 组合键实现了换行,但是按下Enter 也会触发换行,要阻止掉他的默认行为
else if (event.key === 'Enter') { // 阻止掉 Enter 的默认换行行为 event.preventDefault() }
- 文本内容换行后,高度有限,需要自动滚动到最下面,保证内容始终可见
const editor = editorRef.value.textarea editorRef.value.textarea.scrollTop = editor.scrollHeight