问题描述
在three.js的三维场景上面,三维场景里有鼠标的单击事件控制相机旋转,有键盘事件控制相机前进、后退、左右移动。然后要求在三维场景上叠加一个透明的div,div容器中包含一个input搜索框,当input写好后,正常显示,鼠标也可以聚焦到输入框中,但是无法输入英文内容,中文内容可以输入,无法进行删除操作。
原因
我原本以为是父子容器之间的事件冒泡造成的,但是包含three.js的三维场景的div容器和叠加在其上的div容器并非父子关系,阻止事件冒泡也没有用。
经过chatgpt的科普,我了解到事件冲突的存在,三维场景中的键盘事件和input的键盘事件冲突了。
解决方法
直接在三维场景的键盘事件的响应中,判断事件是否在input标签内触发,如果在input标签内触发,就直接return;反之,就正常响应三维场景中的键盘事件。
const element = e.target as HTMLElement;
if (element && element.tagName == 'INPUT') {
// console.log(element.tagName);
return;
}
其他收获
怎样查看容器上绑定了哪些事件
同时我还了解到怎样查看一个容器上绑定了哪些事件,当时排错时,也是发现把三维场景的键盘事件移除后input就能正常输入。参考链接:怎样查看一个容器上绑定了哪些事件
事件执行顺序
我当时还认为和键盘的事件执行顺序有关,我希望input的键盘事件先执行,然后再执行三维场景里的键盘事件,经查资料得知事件的执行顺序是“先绑定,先执行”。
事件冒泡
一个操作会先触发子容器上绑定的事件监听器,然后是父级上绑定的,然后是父级的父级,直到顶级。这也是事件触发的默认顺序。
事件捕获
与事件冒泡的顺序相反,先触发父级容器的事件监听器,然后才是子级。实现它需要将addEventListener的第三个参数设为true。
参考链接:Js事件执行顺序,冒泡、捕获
事件委托
一个父级容器下辖多个子级容器,其中多个子级容器都在监听同一个事件,那么这个事件监听器可以绑定在父级容器上,这就是事件委托。mdn中推荐使用事件委托,说是可以优化js的性能。
input上绑定的事件
input上发生的事件包括focus/keydown/input/keyup/change/blur,由此在做搜索框的时候可以监听input事件,这样输入一个字符就可以执行相应的操作。
参考链接:输入框事件监听(一):keydown、keyup、input