Vue实现输入框@功能的示例代码

目录
  • 前言
  • 成员列表
    • 创建
    • 使用
  • 输入框
    • 获取光标的坐标
    • 保存光标
    • 插入文本
    • 运行结果
  • 总结

前言

前几篇文章中分别介绍了如何实现聊天输入框的双向绑定、回车键发送、粘贴文本图片等功能,本着完善输入框的目的,文本重点介绍聊天框如何实现@功能。

文章回顾:

Vue实现contenteditable元素双向绑定的方法详解

Vue实现输入框回车发送和粘贴文本与图片功能

首先需要先理清思路:

  • 成员列表组件,需要根据光标的位置调整,点击成员项时回调成员信息
  • 获取光标的位置坐标(x值,y值)
  • 输入框失焦时记录光标
  • 成员列表回调时,将成员信息插入到光标位置,在此之前需要先恢复之前的光标
  • 将光标移动到新的位置

既然有了思路,那么就可以一步一步实现。

成员列表

创建

实现成员列表的方式比较简单,其实就是一个列表,一个简单的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>

使用

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

// 核心代码
...
// 选择成员时插入数据,并关闭弹窗
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;
    }
},
...

输入框

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

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

获取光标的坐标

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

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);
    }
},

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

插入文本

// 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);
},

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

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

简单点,就采用setTimeout实现。

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

运行结果

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

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

总结

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

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

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

至此,输入框的功能就基本完善了。需要看完整代码的可移步 项目地址

以上就是Vue实现输入框@功能的示例代码的详细内容,更多关于Vue输入框@功能的资料请关注我们其它相关文章!

(0)

相关推荐

  • vue实现短信验证码输入框

    本文实例为大家分享了vue实现短信验证码输入框的具体代码,供大家参考,具体内容如下 先上最终效果 (此处代码显示的是短信验证码框的效果   其余部分并未放上去) html <div class="code"> <input id="first" class="inputStyle" v-model="code[0]" style="border-top-left-radius: 12px; bord

  • 如何通过Vue实现@人的功能

    本文采用vue,同时增加鼠标点击事件和一些页面小优化 基本结构 新建一个sandBox.vue文件编写功能的基本结构 <div class="content"> <!--文本框--> <div class="editor" ref="divRef" contenteditable @keyup="handkeKeyUp" @keydown="handleKeyDown" >

  • vue输入框使用模糊搜索功能的实现代码

    实现原理: 利用js的 indexOf 方法可返回某个指定的字符串值在字符串中首次出现的位置. 模板中的代码 <div class="search"> <!--输入框使用的是vant的输入框组件--> <van-search @input="autoSearch" v-model="value" placeholder="请输入搜索关键词" style="width:90%; displ

  • vue实现输入框自动跳转功能

    本文实例为大家分享了vue实现输入框自动跳转的具体代码,供大家参考,具体内容如下 <template> <div class="inputClass"> <div v-for="(item,index) in list" :key="index"> <input v-model="item.value" type="password" class="inp

  • vue+iview实现手机号分段输入框

    vue + iview 实现一个手机分段的提示框,知识点还没总结,供大家参考,具体内容如下 <template>   <div :class="{'ivu-form-item-error':!valid && dirty && validated}">     <div class="ivu-phone-input ivu-select  ivu-select-multiple ivu-select-default

  • Vue实现输入框@功能的示例代码

    目录 前言 成员列表 创建 使用 输入框 获取光标的坐标 保存光标 插入文本 运行结果 总结 前言 前几篇文章中分别介绍了如何实现聊天输入框的双向绑定.回车键发送.粘贴文本图片等功能,本着完善输入框的目的,文本重点介绍聊天框如何实现@功能. 文章回顾: Vue实现contenteditable元素双向绑定的方法详解 Vue实现输入框回车发送和粘贴文本与图片功能 首先需要先理清思路: 成员列表组件,需要根据光标的位置调整,点击成员项时回调成员信息 获取光标的位置坐标(x值,y值) 输入框失焦时记录

  • vue实现禁止浏览器记住密码功能的示例代码

    查找资料 网上查到的一些方法: 使用 autocomplete="off"(现代浏览器许多都不支持) 使用 autocomplete="new-password" 在真正的账号密码框之前增加相同 name 的 input 框 使用 readonly 属性,在聚焦时移除该属性 初始化 input 框的 type 属性为 text,聚焦时修改为 password 使用 type="text",手动替换文本框内容为星号 "*" 或者

  • Vue实现快捷键录入功能的示例代码

    项目需要在页面使用快捷键,而且需要对快捷键进行维护,然后参考了此篇文章,改成自己的. 记录一下. 首先有一个组件,用来实现快捷键的录入操作. 直接上代码: hotkeyInput.vue <doc> 快捷键输入框 -- 用于快捷键的录入 </doc> <template> <div class="shortcut-key-input" :class="{ cursor: focus }" :style="$prop

  • VUE饿了么树形控件添加增删改功能的示例代码

    本文介绍了VUE饿了么树形控件添加增删改功能的示例代码,分享给大家,具体如下: element-ui树形控件:地址 在原文档中有个案例是有新增和删除功能,但是后来发现其修改的数据并不能直接影响到树形数据,所以采用了 render-content 的API重新写了个组件. 写个开发的步骤,所以文章比较长emmm 大致效果如图: 1.省市API 在网上复制了个省市的list,有两个属性是新增的 isEdit :控制编辑状态 maxexpandId :为现下id的最大值 export default{

  • Vue后台实现点击图片放大功能的示例代码

    目录 需求 代码 父组件 子组件 dom.js util.js types.js 需求 点击小图可以放大,放大后,通过手势等比例放大缩小.左右切换图.旋转.关闭.由于element-ui版本较低不支持使用图片放大的image组件. 代码 父组件 <template> <div> <!-- 放大图 --> <el-image-viewer v-if="showImg" :on-close="closeViewer" :src=

  • vue实现图片滚动的示例代码(类似走马灯效果)

    上次写了一个简单的图片轮播,这个相当于在上面的一些改进.这个组件除了可以进行图片滚动外,也可以嵌入任何内容的标签进行滚动,里面用了slot进行封装. 父: <template> <div id="app"> <er-carousel-index :typeNumber=2 :pageNumber=3 :timeSpace=2 :duration=2 :isOrNotCircle="true" url="/src/js/inde

  • Android实现强制下线功能的示例代码

    一.回顾 上次连载写了两个类,一个类ActivityCollector.java用于管理所有的活动:一个类是BaseActivity.java作为所有活动的父类: 还有一个放在layout目录中的登录界面login.xml 二.登录页面的活动 接下来写一个登录页面的活动,继承自BaseActivity.java package com.example.broadcastbestpractice; import android.content.Intent; import android.os.B

  • django+vue实现注册登录的示例代码

    注册 前台利用vue中的axios进行传值,将获取到的账号密码以form表单的形式发送给后台. form表单的作用就是采集数据,也就是在前台页面中获取用户输入的值.numberValidateForm:前台定义的表单 $axios使用时需要在main.js中全局注册,.then代表成功后进行的操作,.catch代表失败后进行的操作 submitForm(formName) { let data = new FormData() data.append('username',this.number

  • Python实现自动回复QQ消息功能的示例代码

    目录 1.需要安装的模块 2.整体逻辑 3.代码实现 最近在看测试相关的内容,发现自动化测试很好玩,就决定做一个自动回复QQ消息的脚本(我很菜) 1.需要安装的模块 这个自动化脚本需要用到3个模块,如果要使用这个脚本的朋友,自己的python中可能没有安装这些模块,所以就可以安装一下 第1个模块:pyautogui 这个模块主要是用来让程序自动控制鼠标和键盘的一系列操作来达到自动化测试的目的. 在cmd下输入安装命令:pip install pyautogui 第2个模块:pyperclip 这

  • vue 运用mock数据的示例代码

    本文介绍了vue 运用mock数据的示例代码,分享给大家,具体如下: 初始化你的项目 话不用啰嗦,首先初始化你的项目,最简单的就是使用vue-cli啦 vue init webpack 引入mock.js 安装 mockjs npm install --save-dev mockjs 引入到Vue原型上,方便使用 import mockjs from 'mockjs' Vue.prototype.$mock = Vue.$mock = mockjs.mock 以上引入到Vue原型上,可以使用 t

随机推荐