功能介绍
左侧选择数据采集点位,右侧可以选择输入数值、运算符号等操作,配合构建出较为复杂的规则,本文主要讲规则配置部分,左侧选择点位部分比较简单,是一个正常el-table。
大致效果
思路(规则配置部分)
- 左侧使用一个contenteditable为true的div,用于展示可编辑状态,主要是需要光标,然后内部通过v-for去循环当前已经选择的点位、输入值、操作符。
- 右侧使用v-for循环展示按钮列表
遇到的问题
怎么获取当前光标位置
需要获取当前的光标位置,才能正常的新增和删除规则
点位展示的光标聚焦位置不对
点位使用的span展示,但是光标进入了点位信息内部,按期望应该显示在整个蓝色部分后面一点。而操作符号(+)不会出现这样的情况,因为它用的el-input加readonly属性实现,el-input的光标不会进入内部(通过数值输入框发现的)。
在数值输入框里键盘按下删除会把整个输入框删除
猜测是因为按下删除时,删除事件冒泡到外部,直接删除了整个输入框
问题处理
获取当前光标位置
获取光标有两种情况
- 点击了规则编辑框空白位置
- 点击了点位、值输入框、操作符
处理情况1
绑定整个框的点击事件,点击时通过document.getSelection()获得最新光标情况,getSelection会返回anchorNode节点,表示选区开始节点,这里还有个小细节,如图所示两个红色箭头处得到的anchorNode都是同一个元素,需要单独处理一下,我使用$event中的点击位置去做的判断,把第一个箭头处的那部分区域作为判断条件。
处理情况2
如果点击了点位、操作符,通过监听他们的click事件,使得就可以得到最新的光标位置,这种情况始终认为光标在点位、操作符框尾部。
点位展示的光标聚焦位置不对
根据问题处的图片可知,el-input类型的可以正常显示光标。所以,将点位展示改为输入框+realonly属性可以解决该问题。此时,又出现了一个小问题,el-input宽度是不会自适应的,而固定的太宽或太窄都显得比较奇怪,这里我通过文本个数计算了一个大致宽度(英文和符号这些算一半的font-size宽度)。
输入框错误问题删除
输入框内部按下删除键,默认会冒泡到div(属性contenteditable:true)的键盘事件,那个div绑定了键盘按下删除事件,用于删除输入框,所以阻止数值输入框keydown冒泡上去就可以了。
新的问题
点击后规则框后页面完全卡死问题
如图,点击规则框之前,点击查询这些都是正常的,一旦点击规则框,页面直接卡死,cpu显示100%。浏览器是chrome(116.0.5845.97版)
完全卡死问题排查和处理
chrome性能面板
通过性能面板录制的信息来看,各项指标并不高,从箭头处开始完全卡死,下方堆栈信息、节点、监听器没有明显上升,箭头前面的上升部分,是进入弹窗时增加的,也还算正常。箭头处后面CPU状态占用100%,而且是系统占用,并非我的程序中占用,询问了ai,没问到太有用的信息,它建议我检查事件绑定、js是否死循环、添加防抖之类,但是经过检查,代码是没太大问题的。
注释和删除代码
我的页面并非一开始就这样了,而是在我通过ai加了些代码,自己又加了些代码,才导致一点击配置规则就卡死了的。所以,既然通过chrome面板分析不出问题,那就可以尝试去还原和注释代码去逐步发现问题,我把scss和js相关代码的都注释了。
发现问题
通过不断注释,发现问题出在:contenteditable="false"这个属性上的,本来我是为了防止点位和操作符内部被选择上,加的这个属性,删除后,页面恢复了正常。图片中,是我注释删除后简洁的代码。我分析的原因是,外层contenteditable为true,正常点击后会有一个光标落下,但是:contenteditable="false"使得el-input左右侧无法被设置光标(我全部都加了该属性),就导致光标无法正常落下,在浏览器内部处理时,出现了类似死循环的情况,导致页面完全卡死。
有趣的是,我在edge浏览器中也试了下,竟然完全不会卡死,并且光标能正常落下。所以,浏览器对于这个属性处理还是不一样的,我的chrome版本也不算太老,查了一下chrome116版本是2023年8月多发布的,这肯定不算是ie那种老古董。
写在最后
经过不断遇到和解决问题,规则编辑器趋近于正常,这个小小的编辑器虽然功能简单,但是也遇到了不少问题,不得不让人感叹更复杂的编辑器,如富文本编辑器以及vs code等开发工具,确实很厉害。