記一次的case處理——表單元素輕觸不能聚焦在手機上

問題描述:在手機上,發現網頁上所有的表單元素輕觸都不能聚焦

1、第一次探索和嘗試

爲測試元素加上click事件和focus事件,輕觸的時候發現click觸發了,但是focus沒有觸發,有點奇怪啊,第一次的嘗試解決方案:就在click的事件回調函數中調用focus方法;雖然最後聚焦成功了,但是僅僅只是處理了一個表單元素,頁面還有n個元素需要這麼處理,頭疼;所以打算找原因,從底層根本處理問題。

2、定位原因

在google和Baidu上一頓搜索,發現已有類似的問題,是因爲fastclick;問題來了,fastclick是啥?
大家應該都知道移動端裏有雙擊縮放的功能,那瀏覽器是怎麼區分是雙擊還是單擊呢,爲了解決這個問題,瀏覽器是先觸發touch事件,經過touchstart -> touchmove -> touchend ,300ms之後纔會觸發click事件;那又有一個問題了,假如網頁不需要雙擊縮放的效果,那麼300ms就顯得很多餘了,還搞得網頁有點卡卡的感覺,沒有絲滑的感覺很不爽啊,所有就有了fastclick。更詳細文章請看:300ms的由來以及解決辦法
總得說fastclick就是解決300ms的問題,阻止原生的click事件,並立即使用sendClick發送click事件。
fastclick是啥原因導致了不能聚焦,之前怎麼沒有暴露出來呢?
具體定位流程就不說了,直接貼代碼:

		    if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) {
				this.targetElement = null;
				return false;
			}
			this.focus(targetElement);
			this.sendClick(targetElement, event);
			
			if (!deviceIsIOS || targetTagName !== 'select') {
				this.targetElement = null;
				event.preventDefault();
			}
			return false;

這段代碼是fastclick 的touchend中的一段,代表需要觸發點擊事件,並且需要聚焦的,這裏都沒啥問題,是聚焦的focus方法有問題,如下:

FastClick.prototype.focus = function(targetElement) {
		var length;
		if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month' && targetElement.type !== 'email') {
			length = targetElement.value.length;
			targetElement.setSelectionRange(length, length);
		} else {
			targetElement.focus();
		}
	};

普通的input元素是使用setSelectionRange聚焦的,這個方法在高版本的ios上不知爲啥就不能使用了,導致不能聚焦。

3、解決方法

  • 1 使用focus替換setSelectionRange方法,但是這個有操作成本,需要改fastclick源碼
  • 2 直接把fastclick去掉,因爲現在很多瀏覽器已經沒有300ms的延遲了,再配合css解決
html {
	touch-action: manipulation;
}

touch-action屬性詳解

manipulation
瀏覽器只允許進行滾動和持續縮放操作。任何其它被auto值支持的行爲不被支持。啓用平移和縮小縮放手勢,但禁用其他非標準手勢,例如雙擊以進行縮放。 禁用雙擊可縮放功能可減少瀏覽器在用戶點擊屏幕時延遲生成點擊事件的需要。 這是“pan-x pan-y pinch-zoom”(爲了兼容性本身仍然有效)的別名。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章