需求场景: 如下图,希望当点击动态词包中的项目时,可以将词包名插入到光标所在位置。
这其实是版本优化出来的问题,本来标题是只允许一次添加一条的,动态词包直接拼在当前输入框已有的文字后面,比如:要添加一条 你好{帅哥美女}我叫唐伯虎 时, 需要先输入“你好”,再点击{帅哥美女},再输入“我叫唐伯虎”。
当然业务部门感觉一次只能添加一条标题,而且加个词包这么麻烦...巴拉巴拉...没办法,优化吧。
【思路清晰,先看BP】 我们其实就是想做三件事:公平,公平,还是™的公平。 1、获取文本框/文本域中,光标所在的位置。 2、将某个字符串插入到光标所在的位置。 3、如果可以的话,能将选中的文字直接替换成我们想要的字符串。
我们先看第一个问题:如何获取光标在文本框/文本域中的位置 DOM操作有个api可以获取文本框与文本域中已选中的文本起始位置和结束位置。
el.selectionStart // 输入框或文本域中 已选中文字的开始位置
el.selectionEnd // 输入框或文本域中 已选中文字的结束位置
el
就是我们的输入框或者文本域
<template>
<div>
<el-input id="inputArea" v-model="inputValue"></el-input>
</div>
</template>
let el = document.querySelector("#inputArea");
let start = el.selectionStart; // 这就是当前光标所在的位置(字符串中字符的index)
第二步: 将我们需要插入的字符串(如{地区})插入到光标所在位置。
//将输入框内容切成数组,方便后续操作
let inputValueArr = this.inputValue.split('');
// 拿到选中文字的长度(后续可以用来替换选中的文字)
let selectLength = el.selectionEnd - el.selectionStart;
// 将要插入/替换的文字插入/替换(value.name是要插入/替换的字符串)
inputValueArr.splice(el.selectionStart, selectLength, `{${val.name}}`);
// 把数组重新转换为字符串并赋值
this.inputValue = inputValueArr.join('');
this.input(this.inputValue);
到这里其实我们已经完成2和3了。既可以在光标位置插入字符串,也可以将输入框中选中的字符串替换为我们想要的字符串。但是调试的时候发现了另一个问题:当页面中有多个位置需要这样操作时,因为我们的ID相同,所以会导致插入有问题:无法正确的拿到光标位置。
因为我这里是做成表单组件的,我的表单页面又多次用到了这个组件,每个组件内input的id都是相同的,所以如果有遇到和我类似的情况时,可以自己生成个随机数或者拿时间戳拼接一个id,保证每个组件内的input的id是唯一的即可。
我这个方法可能比较笨,大家可能有更好的方式来实现,欢迎指教,谢谢~