Vue实战:轻松掌握输入框@功能实现技巧

news2024/9/20 18:45:49

成员列表

创建

实现成员列表的方式比较简单,其实就是一个列表,一个简单的v-for循环就可以搞定,点击时将当前选择的成员项回调给父组件。

新增一个AtPop.vue文件:

<template> <div class="at-pop-index"> <div v-for="(item, index) in listData" :key="index" class="at-pop-item" @click.stop="clickItem(item)">{{item.name}}</div> </div> </template> <script> export default { props: { // 传入需要被@的成员数组 listData: { type: Array, default: () => [] } }, methods: { clickItem(item) { this.$emit('onSelect', item); // 调用父组件处理成员选择的方法,并回传当前选择项 } } } </script>
Copy

使用

在父组件中,注册并使用成员列表组件。我们需要在用户输入@的时候弹出成员列表,因此需要监听用户的输入,然后在用户选择成员后需要关闭。关键是获取光标位置,这个由输入框获取,在父组件只需要使用即可。

// 核心代码 ... // 选择成员时插入数据,并关闭弹窗 onSelect(item) { console.log('onSelect', item); this.$refs.inputBox.insertContent(`${item.name} `); // 有空格 this.isshowAt = false; }, // 输入框输入时回调函数 inputFunc(data, event) { console.log('inputFunc', data, event); if (event.data === '@') { this.isShowAt = true; // 显示弹窗 this.$nextTick(() => { let dom = document.getElementsByClassName('at-pop-index')[0]; // 获取成员列表弹窗,需要放在nextTick中 // 设置位置 dom.style.position = 'fixed'; dom.style.left = Math.floor(data.left + 10) + 'px'; dom.style.top = Math.floor(data.top) + 'px'; dom.style.zIndex = 9999; }) } else { this.isShowAt = false; } }, ...
Copy

输入框

输入框需要处理光标位置的获取、将值插入到光标的位置等,是本次功能实现的核心。

当输入框聚焦时,我们会看到光标闪动,想要获取光标的位置以便于插入数据,则需要借助Selection对象。Selection表示用户选择的一段文本范围或者插入数据的当前位置。既然是获取选取范围,那当前选择范围的index=0就是当前光标的位置。我们想要实现的效果是成员列表跟随光标移动,因此就需要获取光标的坐标值。

获取光标的坐标

let range = window.getSelection().getRangeAt(0); // 获取当前光标 let position = range.getBoundinGClientRect(); // 获取当前光标的位置
Copy

getBoundingClientRect()方法会返回一个DOMRect矩形对象,其包含矩形区域的坐标值。将获取到的坐标值回调给父组件的方法,显示成员列表。

当我们在输入框输入@的时候,页面会出现成员列表,此时输入框还是聚焦的。但是如果我们点击了成员列表的某一项,此时输入框已经失焦了,虽然我们可以获取选择的成员并插入,如果只是简单的字符串追加的话,光标会在下次输入时默认定位到开头;或者我们需要在中间插入选择的成员,会发现没有位置可以插入。因此我们需要在失焦的时候先保存当前光标,并在插入时还原光标。

保存光标

// DivEditable.vue // 失焦 inputBlur(event) { this.selection = this.saveSelection(); this.$emit('blurFunc', event); }, // 失焦时保存光标 saveSelection() { if (!window.getSelection) { return null; } let sel = window.getSelection(); if (sel.getRangeAt && sel.rangeCount) { return sel.getRangeAt(0); } },
Copy

光标暂存了,我们需要将插入成员封装成方法,并可以给父组件调用,这样父组件在获取到成员信息后就可以直接调用。接下来需要使用上面已经保存的光标位置:

插入文本

// DivEditable.vue // 恢复光标 restoreSelection(range) { if (range) { let sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); } }, // 插入数据 insertContent(value) { // this.$refs.editor.focus(); let range, node; this.restoreSelection(this.selection); // 还原失焦前的光标位置 range = window.getSelection().getRangeAt(0); range.collapse(false); // 光标移动到最后 ​ node = range.createContextualFragment(value); let child = node.lastChild; console.log('lastChild', child); range.insertNode(node); // 将光标的起始位置设置在当前插入的元素后面 if (child) { range.setEndAfter(child); range.setStartAfter(child); } ​ let sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); this.$emit('input', this.$refs.editor.innerhtml); },
Copy

其实到这里就基本实现了@功能,但是还有一个问题,当输入框失焦时回调了父组件的blurFunc方法,导致成员列表关闭了,但是数据还没有拿到。处理这种问题,有两种思路:

  • 使用setTimeout设置定时器,延后执行关闭成员列表操作
  • 修改取数逻辑为异步操作,等到数据拿到后才关闭成员列表

简单点,就采用setTimeout实现。

// InputBox.vue blurFunc(event) { // 失焦时延时关闭弹窗,避免还未拿到数据 if (this.isShowAt) { setTimeout(() => { this.isShowAt = false; }, 500); } },
Copy

运行结果

输入框输入@,在光标位置附近弹出成员列表

选择成员后,将成员信息插入到输入框中

总结

本文介绍了实现输入框@功能的方法,简单易上手

主要使用了SelectionRange对象的相关方法,完成对光标的处理以及输入的插入

本文实现的@功能,无法删除时整体删除。目前有两种思路:将@xxx转换为图片并插入到输入框,笔者简单写了demo验证了一下,效率不高,且会有卡顿;另一种方式就是监听退格键,删除时判断删除对象是否被包含着有意义的@xxx中,如果是则整体删除,如果不是则默认的方式删除,这种方式笔者没有尝试,难度比较大。

来源|编程网 作者:泡泡鱼

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

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

相关文章

DIFFUSION 系列笔记| Latent Diffusion Model、Stable Diffusion基础概念、数学原理、代码分析、案例展示

目录 Latent Diffusion Model LDM 主要思想 LDM使用示例 LDM Pipeline LDM 中的 UNET 准备时间步 time steps 预处理阶段 pre-process 下采样过程 down sampling 中间处理 mid processing 上采样 upsampling 后处理 post-process LDM Super Resolution Pipeline…

海康视觉二次开发学习笔记8-从回调函数获取结果

回调函数使用方法 通常在方案或流程执行完成后,就可以获取到流程运行的结果.运行一次流程后,我们就可以获取到流程的渲染结果以及流程的数据结果.那么使用通讯或硬件进行外部触发时,如何获取结果呢? 这种时候就要用到回调函数. 1. 注释原获取结果代码 2. 注册回调函数 在构…

【文献及模型、制图分享】数字技术力量下传统村落景观修复演进的特征与机制研究——以岳阳市张谷英村为例(GIS空间分析、点云提取)

文献介绍 景观修复作为弘扬中华优秀传统文化的重要方式&#xff0c;如何在乡村数字化新时代背景下&#xff0c;把握传统村落景观修复的数字赋能&#xff0c;已成为推动中华优秀传统文化创造性转化与创新性发展亟需解决的科学问题。运用深度访谈、GIS空间分析、点云数据提取等方…

html+css+js网页设计 婚庆类型12个页面

htmlcssjs网页设计 婚庆类型12个页面 网页作品代码简单&#xff0c;可使用任意HTML编辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&#xf…

FreeRTOS 低功耗模式

正如STM32的裸机编程一样&#xff0c;FreeRTOS通用提供了低功耗模式。 前面说的很明白&#xff0c;FreeRTOS的低功耗模式实际上还是基于STM32的低功耗模式指令进入睡眠模式来实现的&#xff0c;并且只要中断来临&#xff0c;就会退出低功耗&#xff0c;FreeRTOS的系统时钟是最底…

猫头虎分享:Python库 Statsmodels 的简介、安装、用法详解入门教程

猫头虎分享&#xff1a;Python库 Statsmodels 的简介、安装、用法详解入门教程 &#x1f42f; 引言 &#x1f3af; 今天猫头虎带您 深入探讨 Statsmodels 这个在数据分析和统计建模领域非常重要的Python库。最近有粉丝在评论区问道&#xff1a;“猫哥&#xff0c;如何使用 St…

USB端点

USB端点 各端点使用循环冗余校验&#xff08;CRC&#xff09;来检测传输中发生的错误。 根据 USB 规范&#xff0c;设备端点是 USB 设备中一个独特的可寻址部分&#xff0c;它作为主机和设备间通信流的信息源或库。 USB 枚举和配置一节介绍了设备向默认地址做出响应的步骤。 枚…

能进大厂的自动化测试面试题

前言 每次到金九银十都避免不了要聊一聊面试题了&#xff0c;如今九月已经是中下旬了&#xff0c;马上就要到十月份了&#xff0c;还在投简历找工作的小伙伴可以看看我这几天发的文章&#xff0c;最近发的都是面试题&#xff0c;如果需要笔者教一下大家怎么写简历的小伙伴可以…

光伏高压并网升压箱变

在当今能源领域的变革浪潮中&#xff0c;光伏能源以其清洁、可再生的显著优势&#xff0c;成为了备受瞩目的焦点。而光伏高压并网升压箱变&#xff0c;则是实现光伏电能顺利接入高压电网的核心设备。 光伏高压并网升压箱变宛如光伏能源系统中的一位“大力士”&#xff0c;承担着…

一张图浏览CSS Functions

点我CSS Functions思维导图下载 函数文章链接示例属性函数var attr env介绍访问文章示例地址

银河麒麟编译opencv库并配置qt环境

1.opencv下载版本:opencv4.5.5,qt安装的是qt5.12.11,系统版本: 2.首先应该安装cmake工具: 下载地址:https://cmake.org/download/ 安装步骤: 1)解压; 2)进入解压后的文件夹cd cmake-3.30.2 3)./bootstrap 4)sudo make 5)sudo make install 3.下载opencv,下…

实现 GridLayoutManger 和 StaggeredGridLayoutManager 混排的工具类

序言 最近项目中要实现瀑布流的混排&#xff0c;于是写了一些工具类来实现。使用了这个工具类&#xff0c;可以处理混排&#xff0c;可以处理间距。都集成在一个接口中。 最后效果类似这样。 工具类 GridItemUI 下面的这个类是用来实现在GridLayouManger中混排的。 packag…

硬件-PCB-正片(常用默认)和负片

文章目录 问题&#xff1a;什么是PCB的正片和负片&#xff1f;1.正片设计默认是无铜的&#xff08;常用&#xff09;2.负片设计是默认有铜的3.网友评论道友&#xff1a;我们的对手从来不是别人&#xff0c;而是自己。如果有什么必须战胜&#xff0c;那就是过去的自己。战胜自己…

Nginx 部署前端 Vue 项目全攻略

一、前期准备工作 要将 Vue 项目部署到 Nginx &#xff0c;需要做好以下准备工作&#xff1a; Nginx 的安装&#xff1a; 对于 Centos 系统&#xff0c;可以通过 yum install -y nginx 命令来安装 Nginx 。 对于 Windows 系统&#xff0c;需要在 Nginx 官网下载相应的安装包并…

数据迁移新技能,MongoDB轻松同步至ClickHouse

在当今数据驱动的世界中&#xff0c;企业的成功依赖于对数据的高效管理和精准分析。数据迁移是实现这些目标的关键环节&#xff0c;而选择合适的工具可以让这项工作变得更加轻松和高效。ETLCloud 是一款创新的 ETL&#xff08;提取、转换、加载&#xff09;工具&#xff0c;它提…

(三)了解MySQL 【用户创建和权限/索引】

一、创建用户 DCL主要用于定义数据库的安全性和访问权限&#xff0c;包括创建用户、授予权限、撤销权限等。 CREATE USER 属于DCL因为它关注的是数据库的安全性和用户管理 格式 create user 用户名来源地址 [identified by [password] 密码 ]; 用户名&#xff1a;指…

Web开发:ABP框架中的服务调用原则--避免服务之间的直接依赖

示意图 &#xff08;Service之间可以相互调用&#xff0c;使用依赖倒置原则&#xff1a;例如某个服务可注入到另一个服务&#xff0c;用法&#xff1a;private readonly IyyyService _yyyService;&#xff09; 命名约定 WebAPI 控制器: 建议命名为 XXXXController 或 XXXXMa…

Linux学习(15)-网络编程:滑动窗口、拥塞控制、udp

本节学习内容 1.滑动窗口&#xff08;1.滑动窗口的作用2.如果如果接收端填充的接收窗口为0&#xff0c;发送端接下来怎么处理3.糊涂窗口综合征4.tcp中nagle算法是什么&#xff09; 2.拥塞控制 3.udp协议特点及编程流程 本节可能会用到的指令 ifconfig查看自己的ip地址 pi…

Scrapy添加代理IP池:自动化爬虫的秘密武器

在网络爬虫的世界里&#xff0c;IP地址的频繁更换是防止被目标网站封禁的有效手段。通过在Scrapy中添加代理IP池&#xff0c;你可以轻松实现自动化的IP切换&#xff0c;提高数据抓取的效率和稳定性。今天&#xff0c;我们就来详细讲解一下如何在Scrapy中添加代理IP池&#xff0…

使用 nuxi analyze 命令分析 Nuxt 应用的生产包

title: 使用 nuxi analyze 命令分析 Nuxt 应用的生产包 date: 2024/8/29 updated: 2024/8/29 author: cmdragon excerpt: 使用 nuxi analyze 命令可以帮助你深入了解生产包的结构和大小,从而做出针对性的优化。通过定期分析生产包,你可以识别并解决性能瓶颈,提高应用的加…