有接到需求,需要做一个输入#号,弹出下拉框,进行选择并替换到里面的内容。如下图,支持联想。做的不好,还望提出意见。

可能的情况
1.用户顺序输入#号,然后弹出下拉框。
2.用户左右键移动,再输入#号弹出下拉框。
3.用户鼠标点击某个位置在输入#号,弹出下拉框。
等等
思路
最简单的方法 -- jquery-UI 封装的 Autocomplete() 方法,谁用谁知道,好用!
自己实现
项目中使用vue作为技术栈,交互还是比较方便的。
这里需要了解一下几个知识:
1.window.getSelection() 方法对当前激活选中去(文本高亮处)进行操作。移步JavaScript标准Selection操作 - Rain Man - 博客园
2.可输入div,div的属性 contenteditable,请移步 vue2 实现 div contenteditable="true" 类似于 v-model 的效果 - acco - SegmentFault 思否
3.dom.getBoundingClientRect() 获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。
4.插入节点 insertNode,创建节点 createElement,移除子节点 removeChild 了解一下JS在页面光标位置插入新内容 - 精神领袖 - 博客园
总体思路:
首先获取输入框中输入#号时光标的位置(只能获取到文本中第几位,非可视区域的位置),并保存其位置。然后在当前位置插入一个创建的节点,并获取它的可视区域位置(left,top值),保存后删除该节点。然后通过简单运算,获取到下拉框的绝对定位的left,top值,赋值给下拉框并让其显示。点击下拉框中的任意一项,根据输入#号时的光标位置进行字符串的截取并添加。这样就会插入到输入框中。
效果如图


code-img


注意项
1.Chrome 浏览器,input标签oninput事件中,有 event.data 属性,即为输入的值,刚开始就是使用的 这个属性,在chrome完美运行,退格键,左右键完美运行,无bug。但是忽略了一点,这个属性在 firefox,ie不存在。故在这里,不能够实现。
2.onblur 事件触发 比 onclick 事件快。在弹出下拉框时,我们需要去点击下拉框的内容,就内容插入到我们input输入框内,并将下拉框隐藏。自然而然的会写一个 onblur事件来 是 show 为false,在下拉框的ul中执行点击操作。在实际中 blur 事件先触发,下拉框就会消失掉,这个时候可点击的dom结构已不存在,也就不会触发该事件。解决方法是在 blur事件中,增加一个延时器,延时 将 show 置为 false;
3.可输入的div,测试中不支持input事件。如有错误,还望提出。