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 + '\n' + 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