問題詳情
在嵌入式硬件設備里,測試 “點擊input密碼框,彈出第三方自帶鍵盤,點擊密碼框旁的小眼睛,切換輸入內容加密狀態,鍵盤收起/彈出狀態不變” 的功能邏輯;實際情況卻是 “點擊鍵盤或input框之外的任何地方,鍵盤都會收起” 。
<div class="w-440 h-90 items-center"><text class="fs-24 fw-500 mr-20">密碼/text><input id="input" type="{{type}}" value="{{inputvalue}}" class="w-232 h-90 fs-24 bg-cardBg items-center input-style"style="keyboard: {{ keyboardStyle }}; width: {{ inputwidth }}px;" placeholder="{{placeholder}}"onclick="handleClick" /></div><div onclick="changeType" class="w-98 h-90 absolute" style="top: -2px; right: -2px;"><image if="{{showPassword}}" src="{{'/common/images/eye.png'}}" class="absolute top-25 right-24 w-41 h-41"></image><image else src="{{'/common/images/eye-close.png'}}" class="absolute top-25 right-24 w-41 h-41"></image></div>/////changeType(event) {this.showPassword = !this.showPassword;event.stopPropagation(); // 阻止冒泡},
(頁面編寫基于Vela JS框架)
問題分析
由于是第三方鍵盤,暫時看不到其底層處理方式,初步判斷出兩個邏輯,一是鍵盤的彈出和input框的focus事件相關,二是鍵盤彈出時,會默認在整屏生成蒙層,用戶點擊時觸發蒙層綁定的交互事件,判斷如果是非input框范圍,則收起鍵盤(大眾邏輯)
解決思路
思路1:不去考慮第三方鍵盤的底層處理方式,在用戶點擊小眼睛時,強制觸發input框的focus事件
changeType(event) {this.showPassword = !this.showPassword;if (this.focus) {this.$element("input").focus({focus: true})}event.stopPropagation(); // 阻止冒泡},
結果導致,點擊小眼睛時鍵盤閃爍?外加需要點擊兩次小眼睛才會切換小眼睛的狀態,就像是生成了兩個蒙層,點兩次才能點到小眼睛(看不到源代碼,咱也是瞎猜)
思路2:如果蒙層上綁定的是onclick事件(大眾邏輯),我們可以在小眼睛上綁定一個比onclick事件更快響應的事件,并在事件處理函數內,阻止事件冒泡/穿透到蒙層
這里就涉及到,click和touch事件的觸發順序了
事件觸發順序:touchstart → touchmove → touchend → click
click與touchstart觸發時間差約300ms,因需區分雙擊和單擊
我們雖然無法確認蒙層是位于小眼睛的上層還是下層,但只要小眼睛上事件能觸發,我們就可以將小眼睛上綁定的事件改為最快響應的touchstart
,并阻止事件冒泡/穿透
<div ontouchstart="changeType" class="w-98 h-90 absolute" style="top: -2px; right: -2px;">...</div>/// changeType(event) {this.showPassword = !this.showPassword;if (this.focus) {this.$element("input").focus({focus: true})}event.stopPropagation(); // 阻止冒泡event.preventDefault(); // 阻止默認事件},
問題解決了!鍵盤不閃了,小眼睛也能正常點擊
但是又想到小眼睛的點擊沒有默認事件需要阻止,就把event.preventDefault();
刪了,測試無影響;又想到event.stopPropagation();
生效的前提是,蒙層是小眼睛的祖先元素,為了確認又把event.stopPropagation();
刪了,發現也沒有影響…
奇怪啊,所以解決這個問題的關鍵,僅僅只是將click
改為了touchstart
?難道小眼睛的閃爍是click
的300ms延遲導致的?想不明白了…
結果就這么簡單解決了…
<div ontouchstart="changeType" class="w-98 h-90 absolute" style="top: -2px; right: -2px;">...</div>/// changeType(event) {this.showPassword = !this.showPassword;if (this.focus) {this.$element("input").focus({focus: true})}},