浅谈FastClick 填坑及源码解析(5)
这段比较长,我们主要看这段:
} else if (this.needsFocus(targetElement)) { //非label则识别是否需要focus的元素 //手势停留在组件元素时长超过100ms,则置空this.targetElement并返回 //(而不是通过调用this.focus来触发其聚焦事件,走的原生的click/focus事件触发流程) //这也是为何文章开头提到的问题中,稍微久按一点(超过100ms)textarea是可以把光标定位在正确的地方的原因 //另外iOS下有个意料之外的bug——如果被点击的元素所在文档是在iframe中的,手动调用其focus的话, //会发现你往其中输入的text是看不到的(即使value做了更新),so这里也直接返回 if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) { this.targetElement = null; return false; } this.focus(targetElement); this.sendClick(targetElement, event); //立即触发其click事件,而无须等待300ms //iOS4下的 select 元素不能禁用默认事件(要确保它能被穿透),否则不会打开select目录 //有时候 iOS6/7 下(VoiceOver开启的情况下)也会如此 if (!deviceIsIOS || targetTagName !== 'select') { this.targetElement = null; event.preventDefault(); } return false; }
其中 this.needsFocus 用于判断给定元素是否需要通过合成click事件来模拟聚焦:
//判断给定元素是否需要通过合成click事件来模拟聚焦 FastClick.prototype.needsFocus = function(target) { switch (target.nodeName.toLowerCase()) { case 'textarea': return true; case 'select': return !deviceIsAndroid; //iOS下的select得走穿透点击才行 case 'input': switch (target.type) { case 'button': case 'checkbox': case 'file': case 'image': case 'radio': case 'submit': return false; } return !target.disabled && !target.readOnly; default: //带有名为“bneedsfocus”的class则返回true return (/\bneedsfocus\b/).test(target.className); } };
另外这段说明了为何稍微久按一点(超过100ms)textarea ,我们是可以把光标定位在正确的地方(会绕过后面调用 this.focus 的方法):
//手势停留在组件元素时长超过100ms,则置空this.targetElement并返回 //(而不是通过调用this.focus来触发其聚焦事件,走的原生的click/focus事件触发流程) //这也是为何文章开头提到的问题中,稍微久按一点(超过100ms)textarea是可以把光标定位在正确的地方的原因 //另外iOS下有个意料之外的bug——如果被点击的元素所在文档是在iframe中的,手动调用其focus的话, //会发现你往其中输入的text是看不到的(即使value做了更新),so这里也直接返回 if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) { this.targetElement = null; return false; }
内容版权声明:除非注明,否则皆为本站原创文章。