vue3 实现一个简单的输入框

需求背景

需要一个输入框,可以输入文字,添加表情,一开始用了富文本编辑器,有点大材小用,所以自己封装一个输入框组件。支持输入文字,选择表情/插入表情,支持组合键换行,使用enter
进行提交

效果图

在这里插入图片描述

技术实现

  1. 通过原生textarea实现
  2. 通过 v-model 来实现 父子组件的数据传递,子组件监听数据的变化,向外emit('update:modelValue', inputValue),保证父组件能更新绑定的值
  3. 每次插入时,需要重新聚焦更新光标位置
  4. 通过向外 暴露的 (__insertText),来实现插入表情/文字
  5. 通过向外暴露的(_clear) 输入完毕发送后,需要clear 掉输入框的内容
  6. 通过向外暴露的(__isEmpty) 来判断是否有内容,如果没内容,做按钮的禁用状态(当然也可以直接用父组件绑定的值)
  7. 父组件通过ref 就可以调用以上方法,来做操作。比如发送完数据,调clear清空内容,如果输入框没有内容,则调用isEmpty,做按钮的一些状态

代码实现(子组件)

/*** 自定义文本输入框组件*/import { ref, watch } from 'vue'
import { ElInput } from 'element-plus'export default defineComponent({props: {modelValue: {type: String,default: ''}},emits: ['update:modelValue', 'chatSend'],setup(props, { emit, expose }) {const { t } = useI18n()const editorRef = ref()const disabled = ref(false)const valueHtml = ref(props.modelValue)const currentEvent = ref()watch(() => valueHtml.value,() => {emit('update:modelValue', valueHtml.value)})// 插入元素const _insertText = async (msg: string) => {const msgLength = msg.lengthconst editor = currentEvent.valueif (editor) {const startPos = editor.selectionStartvalueHtml.value = `${valueHtml.value.substring(0, startPos)}${'' + msg}${valueHtml.value.substring(startPos)}`_focus()nextTick(() => {// 此处是 根据元素的长度,来设置光标位置editor.setSelectionRange(startPos + msgLength, startPos + msgLength)})}}// focusconst _focus = () => {editorRef.value && editorRef.value.focus()}// 清空编辑器const _clear = () => {editorRef.value && editorRef.value.clear()}// 是否内容为空const _isEmpty = () => {const str = valueHtml.value.trim().replace(/\n/g, '')return str === '' || str.length == 0 || typeof str === 'undefined'}// 禁用编辑器const _disable = () => {disabled.value = true}// 解除禁用编辑器const _enable = () => {disabled.value = false}const handleKeyDown = (event: KeyboardEvent) => {currentEvent.value = event.target as HTMLInputElement// 定义组合键 Mapconst shortCutKeys: (keyof KeyboardEvent)[] = ['metaKey', 'altKey', 'ctrlKey', 'shiftKey']const isEnterKey = event.code === '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.textareaeditorRef.value.textarea.scrollTop = editor.scrollHeight// 设置光标位置为: start 和 end 相同,光标会移动到换行符后面的新行首currentEvent.value.setSelectionRange(cursorPosition + 1, cursorPosition + 1)})} else if (event.code === 'Enter') {// 阻止掉 Enter 的默认换行行为event.preventDefault()emit('chatSend')}}// 向外暴露方法expose({_insertText,_clear,_disable,_isEmpty,_enable,_focus})return () => (<ElInputref={editorRef}v-model={valueHtml.value}type="textarea"disabled={disabled.value}onKeydown={handleKeyDown}/>)}
})

代码实现(父组件调用)

  • 输入框组件

<base-editorref="chatEditorRef"v-model="inputText"@chat-send="sendText"></base-editor>
  • 工具栏组件

<ChatTools :chat-tools-list="newChatToolsList" @get-emoji="getToolsMsg" />

当我们点击工具栏组件,就会获取到工具栏的文字/表情/或者插入的xxx
,此时根据引用,调用输入框的暴露出的_insertText方法,直接就插入进去

const getToolsMsg = async (msg: string) => {chatEditorRef.value._insertText(msg)
}

其他方法调用

  • _isEmpty(): 未输入,按钮是禁用状态
 <el-button :disabled="chatEditorRef?._isEmpty()" @click="sendText">

当然你也可以直接使用绑定的输入框的变量去判断

<el-button :disabled="!inputText" @click="sendText">
  • _clear(): 提交完请求,清空输入框
chatEditorRef.value._clear()

关于插入的问题

光标位置的获取,根据元素插入位置,光标换行,支持快捷键等。可以参考上一篇文章
https://blog.csdn.net/qq_38845858/article/details/135769222?spm=1001.2014.3001.5502

总结

  1. 原生其实也可以实现,没必要用一个很重的富文本编辑器
  2. 做表情插入,或者其他插入,都是工具栏,和输入框组件的关系是兄弟组件的关系,兄弟组件之间,怎么做数据传递,事件传递,怎么设计

(1) 父组件作为中介

(2)事件总线通过订阅/发布做消息通知

(3)仓库vuex/pina

事件总线还是能不用就不用,因为全局性的东西,用着爽,后面复杂了,就乱了。而且 事件总线是发布订阅,你还得注意销毁,存仓库 又不太合适,子组件自己暴露出方法,让其他组件调用,感觉目前是最简单的方式了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/708850.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DPU:未来计算的三大支柱之一

随着计算领域的不断发展&#xff0c;数据处理单元&#xff08;DPU&#xff09;的出现正在重塑数据中心和计算架构的未来。在本文中&#xff0c;我们深入探讨了DPU在该领域的重要性和作用&#xff0c;并将其与传统的中央处理器&#xff08;CPU&#xff09;和图形处理单元&#x…

2024年小程序云开发CMS内容管理无法使用,无法同步内容模型到云开发数据库的解决方案,回退老版本CMS内容管理的最新方法

一&#xff0c;问题描述 最近越来越多的同学找石头哥&#xff0c;说cms用不了&#xff0c;其实是小程序官方最近又搞大动作了&#xff0c;偷偷的升级的云开发cms&#xff08;内容管理&#xff09;以下都称cms&#xff0c;不升级不要紧&#xff0c;这一升级&#xff0c;就导致我…

亚马逊云科技实时 AI 编程助手 Amazon CodeWhisperer,开发快人一步

​ 亚马逊云科技&#xff1a;https://mic.anruicloud.com/url/1024 ​ Amazon CodeWhisperer 是一款 AI 编码配套应用程序&#xff0c;可在 IDE 中生成 整行代码和完整的函数代码建议&#xff0c;以帮助您更快地完成更多工作。在本系列 文章中&#xff0c;我们将为您详细介绍 A…

学习阶段单片机买esp32还是stm32?

学习阶段单片机买esp32还是stm32? 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「stm32的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xf…

5G时代对于工业化场景应用有什么改善

5G 不仅仅是 4G 的技术升级&#xff0c;而是将平板电脑和智能手机的技术升级。除了更好的高清视频流和其他高带宽应用&#xff0c;消费者不会注意到很多性能差异。然而&#xff0c;在工业领域&#xff0c;5G 代表着巨大的飞跃。 在工厂和厂房内&#xff0c; 设备的Wi-Fi 网络经…

el-table实现转置表格

vue版本&#xff1a;vue2.6.10 elementui版本&#xff1a;2.15.14 实现效果&#xff1a;el-table实现行列互换 代码&#xff1a; <template><div class"app-container"><span>原始数据</span><el-table:data"datas"border>…

自动化信息抽取:提升物资仓库管理效率的实践案例

一、引言 在当今快节奏的供应链管理中&#xff0c;物资仓库的信息抽取和处理是确保物流效率的关键环节。我曾参与的一个项目&#xff0c;正是针对这一需求而设计。该项目的核心目标是优化收货与入库流程&#xff0c;通过先进的信息抽取技术&#xff0c;我们能够自动接收并处理来…

MYSQL--JDBC*

一.介绍: 1.JDBC是一种用于执行SQL于语句的JAVA API,JDBC是一种使用JAVA访问数据库的执行规范标准,能够为不同的数据库提供统一的访问!由一组使用JAVA语言编写的接口以及类组成的 2.JDBC核心的类以及相关的接口主要有: DriverManager 注册驱动 Connection 使用…

代码随想录刷题笔记-Day25

1. 分割回文串 131. 分割回文串https://leetcode.cn/problems/palindrome-partitioning/ 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 示例 1&#xf…

购房合同的注意事项是什么呢?房子备案需要多久?

房屋登记需要多长时间&#xff1f; 购房合同要注意什么&#xff1f; 2019/02/20 10:02:07 来源&#xff1a;方天下观点&#xff08;6993&#xff09; [摘要] 购买房屋后&#xff0c;需要向房管部门办理房屋登记。 这样可以证明房子是在业主名下的&#xff0c;所以需要了解房屋…

c++学习记录 deque容器—排序

算法&#xff1a; sort(iterator beg,iterator end); //对beg和end区间内元素进行排序 #include<iostream> using namespace std; #include<deque> #include<algorithm>//标准算法头文件void printDeque(const deque<int>& d) {for …

FPGA-时钟管理单元

时钟管理单元(Clock Management Tile, CMT) : 即时钟管理片,是FPGA器件中一个十分重要的时钟资源。能够对内部和外部的时钟去偏斜、去抖动,同时还支持频率合成、分倍频等功能。 举例&#xff0c;下面这个例子数据从FIFO输出时钟频率为125MHZ&#xff0c;这个时钟频率可以通过…

flink重温笔记(八):Flink 高级 API 开发——flink 四大基石之 Window(涉及Time)

Flink学习笔记 前言&#xff1a;今天是学习 flink 的第八天啦&#xff01;学习了 flink 高级 API 开发中四大基石之一&#xff1a; window&#xff08;窗口&#xff09;知识点&#xff0c;这一部分只要是解决数据窗口计算问题&#xff0c;其中时间窗口涉及时间&#xff0c;计数…

Bert基础(五)--解码器(下)

1、 多头注意力层 下图展示了Transformer模型中的编码器和解码器。我们可以看到&#xff0c;每个解码器中的多头注意力层都有两个输入&#xff1a;一个来自带掩码的多头注意力层&#xff0c;另一个是编码器输出的特征值。 让我们用R来表示编码器输出的特征值&#xff0c;用M来…

【JavaEE进阶】 Spring AOP快速上手

文章目录 &#x1f343;什么是AOP&#x1f333;什么是Spring AOP&#x1f334;上手Spring AOP&#x1f6a9;引入依赖&#x1f6a9;编写AOP程序 ⭕总结 &#x1f343;什么是AOP AOP是Aspect Oriented Programming的简称&#xff08;又称为面向切⾯编程&#xff09; 什么是面向…

电力运维是做什么的?电力行业智能运维工作内容?

电力行业智能运维工作内容具体涉及哪些关键任务&#xff1f;实施智能运维过程中&#xff0c;如何利用现代信息技术、人工智能和大数据分析来提升电力系统的运行效率与维护响应速度?在电力行业中引入智能运维后&#xff0c;对于预防性维护、故障诊断、设备寿命预测以及成本控制…

33-k8s项目实战-02-k8s的ca证书有效期更新

一、概述 我们知道&#xff0c;k8s各项组件之间的通信&#xff0c;都是使用https协议进行的&#xff0c;也就是ca证书&#xff0c;那么我们也知道ca证书都是有“有限期的”&#xff0c;一旦过期&#xff0c;系统就无法进行通信了&#xff1b; 这也是k8s在企业当中经常遇到的证书…

亿道信息新三防平板EM-I10J,性能和价格成最大亮点

亿道信息近期推出了一款新三防平板电脑名为EM-I10J&#xff0c;这款设备上市的初衷是为了在满足客户作业需求的同时为其提供更合适的价格选择&#xff0c;但这并不意味着EM-I10J的实力可以被小觑。 外观上I10J与之前的I10U并无不同之处&#xff0c;同样是10.1英寸高清电容式触…

《TCP/IP详解 卷一》第10章 UDP和IP分片

目录 10.1 引言 10.2 UDP 头部 10.3 UDP校验和 10.4 例子 10.5 UDP 和 IPv6 10.6 UDP-Lite 10.7 IP分片 10.7.1 例子&#xff1a;IPV4 UDP分片 10.7.2 重组超时 10.8 采用UDP的路径MTU发现 10.9 IP分片和ARP/ND之间的交互 10.10 最大UDP数据报长度 10.11 UDP服务器…

华为OD技术面试案例3-2024年

技术一面&#xff1a; 1.手撕代码&#xff0c;算法题&#xff1a; 【最小路径和】 手撕代码通过&#xff0c;面试官拍了照片 2.深挖项目&#xff0c;做过的自认为最好的一个项目&#xff0c;描述做过的项目的工作过程&#xff0c;使用到哪些技术&#xff1f; 技术二面&…