;
(function() {'use strict';//构造函数function FastClick(layer, options) {var oldOnClick;options = options || {};//是否开始追踪click事件this.trackingClick = false;//存储第一次按下时间戳this.trackingClickStart = 0;//目标元素this.targetElement = null;//存放坐标值Xthis.touchStartX = 0;//存放坐标值Ythis.touchStartY = 0;//主要hack iOS4下的一个怪异问题this.lastTouchIdentifier = 0;//用于区分是click还是Touchmove,若出点移动超过该值则视为touchmovethis.touchBoundary = options.touchBoundary || 10;// 绑定了FastClick的元素,一般是是bodythis.layer = layer;//双击最小点击时间差this.tapDelay = options.tapDelay || 200;//长按最大时间this.tapTimeout = options.tapTimeout || 700;//如果是属于不需要处理的元素类型,则直接返回if(FastClick.notNeeded(layer)) {return;}//语法糖,兼容一些用不了 Function.prototype.bind 的旧安卓//所以后面不走 layer.addEventListener('click', this.onClick.bind(this), true);function bind(method, context) {return function() {return method.apply(context, arguments);};}var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'];var context = this;for(var i = 0, l = methods.length; i < l; i++) {context[methods[i]] = bind(context[methods[i]], context);}//安卓则做额外处理if(deviceIsAndroid) {layer.addEventListener('mouseover', this.onMouse, true);layer.addEventListener('mousedown', this.onMouse, true);layer.addEventListener('mouseup', this.onMouse, true);}layer.addEventListener('click', this.onClick, true);layer.addEventListener('touchstart', this.onTouchStart, false);layer.addEventListener('touchmove', this.onTouchMove, false);layer.addEventListener('touchend', this.onTouchEnd, false);layer.addEventListener('touchcancel', this.onTouchCancel, false);// 兼容不支持 stopImmediatePropagation 的浏览器(比如 Android 2)if(!Event.prototype.stopImmediatePropagation) {layer.removeEventListener = function(type, callback, capture) {var rmv = Node.prototype.removeEventListener;if(type === 'click') {rmv.call(layer, type, callback.hijacked || callback, capture);} else {rmv.call(layer, type, callback, capture);}};layer.addEventListener = function(type, callback, capture) {var adv = Node.prototype.addEventListener;if(type === 'click') {//留意这里 callback.hijacked 中会判断 event.propagationStopped 是否为真来确保(安卓的onMouse事件)只执行一次//在 onMouse 事件里会给 event.propagationStopped 赋值 trueadv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {if(!event.propagationStopped) {callback(event);}}), capture);} else {adv.call(layer, type, callback, capture);}};}// 如果layer直接在DOM上写了 onclick 方法,那我们需要把它替换为 addEventListener 绑定形式if(typeof layer.onclick === 'function') {oldOnClick = layer.onclick;layer.addEventListener('click', function(event) {oldOnClick(event);}, false);layer.onclick = null;}}/*** Windows Phone 8.1 fakes user agent string to look like Android and iPhone.** @type boolean*/var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0;/*** Android requires exceptions.** @type boolean*/var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone;/*** iOS requires exceptions.** @type boolean*/var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone;/*** iOS 4 requires an exception for select elements.** @type boolean*/var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent);/*** iOS 6.0-7.* requires the target element to be manually derived** @type boolean*/var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS [6-7]_\d/).test(navigator.userAgent);/*** BlackBerry requires exceptions.** @type boolean*/var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0;//判断元素是否要保留穿透功能FastClick.prototype.needsClick = function(target) {switch(target.nodeName.toLowerCase()) {// disabled的inputcase 'button':case 'select':case 'textarea':if(target.disabled) {return true;}break;case 'input':// file组件必须通过原生click事件点击才有效if((deviceIsIOS && target.type === 'file') || target.disabled) {return true;}break;case 'label':case 'iframe':case 'video':return true;}//元素带了名为“bneedsclick”的class也返回truereturn(/\bneedsclick\b/).test(target.className);};//判断给定元素是否需要通过合成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则返回truereturn(/\bneedsfocus\b/).test(target.className);}};//合成一个click事件并在指定元素上触发FastClick.prototype.sendClick = function(targetElement, event) {var clickEvent, touch;// 在一些安卓机器中,得让页面所存在的 activeElement(聚焦的元素,比如input)失焦,否则合成的click事件将无效if(document.activeElement && document.activeElement !== targetElement) {document.activeElement.blur();}touch = event.changedTouches[0];// 合成(Synthesise) 一个 click 事件// 通过一个额外属性确保它能被追踪(tracked)clickEvent = document.createEvent('MouseEvents');clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);clickEvent.forwardedTouchEvent = true; // fastclick的内部变量,用来识别click事件是原生还是合成的targetElement.dispatchEvent(clickEvent); //立即触发其click事件};FastClick.prototype.determineEventType = function(targetElement) {//安卓设备下 Select 无法通过合成的 click 事件被展开,得改为 mousedownif(deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {return 'mousedown';}return 'click';};//设置元素聚焦事件FastClick.prototype.focus = function(targetElement) {var length;// 组件建议通过setSelectionRange(selectionStart, selectionEnd)来设定光标范围(注意这样还没有聚焦// 要等到后面触发 sendClick 事件才会聚焦)// 另外 iOS7 下有些input元素(比如 date datetime month) 的 selectionStart 和 selectionEnd 特性是没有整型值的,// 导致会抛出一个关于 setSelectionRange 的模糊错误,它们需要改用 focus 事件触发if(deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month') {length = targetElement.value.length;targetElement.setSelectionRange(length, length);} else {//直接触发其focus事件targetElement.focus();}};/*** 检查target是否一个滚动容器里的子元素,如果是则给它加个标记*/FastClick.prototype.updateScrollParent = function(targetElement) {var scrollParent, parentElement;scrollParent = targetElement.fastClickScrollParent;// Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the// target element was moved to another parent.if(!scrollParent || !scrollParent.contains(targetElement)) {parentElement = targetElement;do {if(parentElement.scrollHeight > parentElement.offsetHeight) {scrollParent = parentElement;targetElement.fastClickScrollParent = parentElement;break;}parentElement = parentElement.parentElement;} while (parentElement);}// 给滚动容器加个标志fastClickLastScrollTop,值为其当前垂直滚动偏移if(scrollParent) {scrollParent.fastClickLastScrollTop = scrollParent.scrollTop;}};/*** 返回目标元素*/FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {// 一些较老的浏览器,target 可能会是一个文本节点,得返回其DOM节点if(eventTarget.nodeType === Node.TEXT_NODE) {return eventTarget.parentNode;}return eventTarget;};FastClick.prototype.onTouchStart = function(event) {var targetElement, touch, selection;// 多指触控的手势则忽略if(event.targetTouches.length > 1) {return true;}targetElement = this.getTargetElementFromEventTarget(event.target); //一些较老的浏览器,target 可能会是一个文本节点,得返回其DOM节点touch = event.targetTouches[0];if(deviceIsIOS) { //IOS处理// 若用户已经选中了一些内容(比如选中了一段文本打算复制),则忽略selection = window.getSelection();if(selection.rangeCount && !selection.isCollapsed) {return true;}if(!deviceIsIOS4) { //是否IOS4//怪异特性处理——若click事件回调打开了一个alert/confirm,用户下一次tap页面的其它地方时,新的touchstart和touchend//事件会拥有同一个touch.identifier(新的 touch event 会跟上一次触发alert点击的 touch event 一样),//为避免将新的event当作之前的event导致问题,这里需要禁用默认事件//另外chrome的开发工具启用'Emulate touch events'后,iOS UA下的 identifier 会变成0,所以要做容错避免调试过程也被禁用事件了if(touch.identifier && touch.identifier === this.lastTouchIdentifier) {event.preventDefault();return false;}this.lastTouchIdentifier = touch.identifier;// 如果target是一个滚动容器里的一个子元素(使用了 -webkit-overflow-scrolling: touch) ,而且满足:// 1) 用户非常快速地滚动外层滚动容器// 2) 用户通过tap停止住了这个快速滚动// 这时候最后的'touchend'的event.target会变成用户最终手指下的那个元素// 所以当快速滚动开始的时候,需要做检查target是否滚动容器的子元素,如果是,做个标记// 在touchend时检查这个标记的值(滚动容器的scrolltop)是否改变了,如果是则说明页面在滚动中,需要取消fastclick处理this.updateScrollParent(targetElement);}}this.trackingClick = true; //做个标志表示开始追踪click事件了this.trackingClickStart = event.timeStamp; //标记下touch事件开始的时间戳this.targetElement = targetElement;//标记touch起始点的页面偏移值this.touchStartX = touch.pageX;this.touchStartY = touch.pageY;// this.lastClickTime 是在 touchend 里标记的事件时间戳// this.tapDelay 为常量 200 (ms)// 此举用来避免 phantom 的双击(200ms内快速点了两次)触发 click// 反正200ms内的第二次点击会禁止触发点击的默认事件if((event.timeStamp - this.lastClickTime) < this.tapDelay) {event.preventDefault();}return true;};//判断是否移动了//this.touchBoundary是常量,值为10//如果touch已经移动了10个偏移量单位,则应当作为移动事件处理而非click事件FastClick.prototype.touchHasMoved = function(event) {var touch = event.changedTouches[0],boundary = this.touchBoundary;if(Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {return true;}return false;};FastClick.prototype.onTouchMove = function(event) {//不是需要被追踪click的事件则忽略if(!this.trackingClick) {return true;}// 如果target突然改变了,或者用户其实是在移动手势而非想要click// 则应该清掉this.trackingClick和this.targetElement,告诉后面的事件你们也不用处理了if(this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {this.trackingClick = false;this.targetElement = null;}return true;};//找到label标签所映射的组件,方便让用户点label的时候直接激活该组件FastClick.prototype.findControl = function(labelElement) {// 有缓存则直接读缓存着的if(labelElement.control !== undefined) {return labelElement.control;}// 获取指向的组件if(labelElement.htmlFor) {return document.getElementById(labelElement.htmlFor);}// 没有for属性则激活页面第一个组件(labellable 元素)return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea');};FastClick.prototype.onTouchEnd = function(event) {var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;if(!this.trackingClick) {return true;}// 避免 phantom 的双击(200ms内快速点了两次)触发 click// 我们在 ontouchstart 里已经做过一次判断了(仅仅禁用默认事件),这里再做一次判断if((event.timeStamp - this.lastClickTime) < this.tapDelay) {this.cancelNextClick = true; //该属性会在 onMouse 事件中被判断,为true则彻底禁用事件和冒泡return true;}//this.tapTimeout是常量,值为700//识别是否为长按事件,如果是(大于700ms)则忽略if((event.timeStamp - this.trackingClickStart) > this.tapTimeout) {return true;}// 得重置为false,避免input事件被意外取消// 例子见 https://github.com/ftlabs/fastclick/issues/156this.cancelNextClick = false;this.lastClickTime = event.timeStamp; //标记touchend时间,方便下一次的touchstart做双击校验trackingClickStart = this.trackingClickStart;//重置 this.trackingClick 和 this.trackingClickStartthis.trackingClick = false;this.trackingClickStart = 0;// iOS 6.0-7.*版本下有个问题 —— 如果layer处于transition或scroll过程,event所提供的target是不正确的// 所以咱们得重找 targetElement(这里通过 document.elementFromPoint 接口来寻找)if(deviceIsIOSWithBadTarget) { //iOS 6.0-7.*版本touch = event.changedTouches[0]; //手指离开前的触点// 有些情况下 elementFromPoint 里的参数是预期外/不可用的, 所以还得避免 targetElement 为 nulltargetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;// target可能不正确需要重找,但fastClickScrollParent是不会变的targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;}targetTagName = targetElement.tagName.toLowerCase();if(targetTagName === 'label') { //是label则激活其指向的组件forElement = this.findControl(targetElement);if(forElement) {this.focus(targetElement);//安卓直接返回(无需合成click事件触发,因为点击和激活元素不同,不存在点透)if(deviceIsAndroid) {return false;}targetElement = forElement;}} 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;}if(deviceIsIOS && !deviceIsIOS4) {// 滚动容器的垂直滚动偏移改变了,说明是容器在做滚动而非点击,则忽略scrollParent = targetElement.fastClickScrollParent;if(scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {return true;}}// 查看元素是否无需处理的白名单内(比如加了名为“needsclick”的class)// 不是白名单的则照旧预防穿透处理,立即触发合成的click事件if(!this.needsClick(targetElement)) {event.preventDefault();this.sendClick(targetElement, event);}return false;};FastClick.prototype.onTouchCancel = function() {this.trackingClick = false;this.targetElement = null;};//用于决定是否允许穿透事件(触发layer的click默认事件)FastClick.prototype.onMouse = function(event) {// touch事件一直没触发if(!this.targetElement) {return true;}if(event.forwardedTouchEvent) { //触发的click事件是合成的return true;}// 编程派生的事件所对应元素事件可以被允许// 确保其没执行过 preventDefault 方法(event.cancelable 不为 true)即可if(!event.cancelable) {return true;}// 需要做预防穿透处理的元素,或者做了快速(200ms)双击的情况if(!this.needsClick(this.targetElement) || this.cancelNextClick) {//停止当前默认事件和冒泡if(event.stopImmediatePropagation) {event.stopImmediatePropagation();} else {// 不支持 stopImmediatePropagation 的设备(比如Android 2)做标记,// 确保该事件回调不会执行(见126行)event.propagationStopped = true;}// 取消事件和冒泡event.stopPropagation();event.preventDefault();return false;}//允许穿透return true;};//click事件常规都是touch事件衍生来的,也排在touch后面触发。//对于那些我们在touch事件过程没有禁用掉默认事件的event来说,我们还需要在click的捕获阶段进一步//做判断决定是否要禁掉点击事件(防穿透)FastClick.prototype.onClick = function(event) {var permitted;// 如果还有 trackingClick 存在,可能是某些UI事件阻塞了touchEnd 的执行if(this.trackingClick) {this.targetElement = null;this.trackingClick = false;return true;}// 依旧是对 iOS 怪异行为的处理 —— 如果用户点击了iOS模拟器里某个表单中的一个submit元素// 或者点击了弹出来的键盘里的“Go”按钮,会触发一个“伪”click事件(target是一个submit-type的input元素)if(event.target.type === 'submit' && event.detail === 0) {return true;}permitted = this.onMouse(event);if(!permitted) { //如果点击是被允许的,将this.targetElement置空可以确保onMouse事件里不会阻止默认事件this.targetElement = null;}//没有多大意义return permitted;};//销毁Fastclick所注册的监听事件。是给外部实例去调用的FastClick.prototype.destroy = function() {var layer = this.layer;if(deviceIsAndroid) {layer.removeEventListener('mouseover', this.onMouse, true);layer.removeEventListener('mousedown', this.onMouse, true);layer.removeEventListener('mouseup', this.onMouse, true);}layer.removeEventListener('click', this.onClick, true);layer.removeEventListener('touchstart', this.onTouchStart, false);layer.removeEventListener('touchmove', this.onTouchMove, false);layer.removeEventListener('touchend', this.onTouchEnd, false);layer.removeEventListener('touchcancel', this.onTouchCancel, false);};//是否没必要使用到 Fastclick 的检测FastClick.notNeeded = function(layer) {var metaViewport;var chromeVersion;var blackberryVersion;var firefoxVersion;// 不支持触摸的设备if(typeof window.ontouchstart === 'undefined') {return true;}// 获取Chrome版本号,若非Chrome则返回0chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [, 0])[1];if(chromeVersion) {if(deviceIsAndroid) { //安卓metaViewport = document.querySelector('meta[name=viewport]');if(metaViewport) {// 安卓下,带有 user-scalable="no" 的 meta 标签的 chrome 是会自动禁用 300ms 延迟的,所以无需 Fastclickif(metaViewport.content.indexOf('user-scalable=no') !== -1) {return true;}// 安卓Chrome 32 及以上版本,若带有 width=device-width 的 meta 标签也是无需 FastClick 的if(chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {return true;}}// 其它的就肯定是桌面级的 Chrome 了,更不需要 FastClick 啦} else {return true;}}if(deviceIsBlackBerry10) { //黑莓,和上面安卓同理,就不写注释了blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/);if(blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) {metaViewport = document.querySelector('meta[name=viewport]');if(metaViewport) {if(metaViewport.content.indexOf('user-scalable=no') !== -1) {return true;}if(document.documentElement.scrollWidth <= window.outerWidth) {return true;}}}}// 带有 -ms-touch-action: none / manipulation 特性的 IE10 会禁用双击放大,也没有 300ms 时延if(layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') {return true;}// Firefox检测,同上firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [, 0])[1];if(firefoxVersion >= 27) {metaViewport = document.querySelector('meta[name=viewport]');if(metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) {return true;}}// IE11 推荐使用没有“-ms-”前缀的 touch-action 样式特性名if(layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') {return true;}return false;};FastClick.attach = function(layer, options) {return new FastClick(layer, options);};if(typeof define === 'function' && typeof define.amd === 'object' && define.amd) {// AMD. Register as an anonymous module.define(function() {return FastClick;});} else if(typeof module !== 'undefined' && module.exports) {module.exports = FastClick.attach;module.exports.FastClick = FastClick;} else {window.FastClick = FastClick;}
}());
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Demo</title><script src="./fastclick.js"></script><style>div {width: 200px;background: red;Ymargin: 0 auto;height: 200px;color: wheat;font-size: 25px;display: flex;justify-content: center;align-items: center;}</style></head><body><div id="main">FastClick</div><script>FastClick.attach(document.body);document.getElementById("main").addEventListener("click", function(event) {console.log(event.target.innerText)}, false)</script></body></html>

fastclick-源码解析相关推荐

  1. FastClick 填坑及源码解析

    最近产品妹子提出了一个体验issue -- 用 iOS 在手Q阅读书友交流区发表书评时,光标点击总是不好定位到正确的位置: 如上图,具体表现是较快点击时,光标总会跳到 textarea 内容的尾部.只 ...

  2. 谷歌BERT预训练源码解析(二):模型构建

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_39470744/arti ...

  3. 谷歌BERT预训练源码解析(三):训练过程

    目录 前言 源码解析 主函数 自定义模型 遮蔽词预测 下一句预测 规范化数据集 前言 本部分介绍BERT训练过程,BERT模型训练过程是在自己的TPU上进行的,这部分我没做过研究所以不做深入探讨.BE ...

  4. 谷歌BERT预训练源码解析(一):训练数据生成

    目录 预训练源码结构简介 输入输出 源码解析 参数 主函数 创建训练实例 下一句预测&实例生成 随机遮蔽 输出 结果一览 预训练源码结构简介 关于BERT,简单来说,它是一个基于Transfo ...

  5. Gin源码解析和例子——中间件(middleware)

    在<Gin源码解析和例子--路由>一文中,我们已经初识中间件.本文将继续探讨这个技术.(转载请指明出于breaksoftware的csdn博客) Gin的中间件,本质是一个匿名回调函数.这 ...

  6. Colly源码解析——结合例子分析底层实现

    通过<Colly源码解析--框架>分析,我们可以知道Colly执行的主要流程.本文将结合http://go-colly.org上的例子分析一些高级设置的底层实现.(转载请指明出于break ...

  7. libev源码解析——定时器监视器和组织形式

    我们先看下定时器监视器的数据结构.(转载请指明出于breaksoftware的csdn博客) /* invoked after a specific time, repeatable (based o ...

  8. libev源码解析——定时器原理

    本文将回答<libev源码解析--I/O模型>中抛出的两个问题.(转载请指明出于breaksoftware的csdn博客) 对于问题1:为什么backend_poll函数需要指定超时?我们 ...

  9. libev源码解析——I/O模型

    在<libev源码解析--总览>一文中,我们介绍过,libev是一个基于事件的循环库.本文将介绍其和事件及循环之间的关系.(转载请指明出于breaksoftware的csdn博客) 目前i ...

  10. libev源码解析——调度策略

    在<libev源码解析--监视器(watcher)结构和组织形式>中介绍过,监视器分为[2,-2]区间5个等级的优先级.等级为2的监视器最高优,然后依次递减.不区分监视器类型和关联的文件描 ...

最新文章

  1. Squid下Http头信息优先级
  2. 大厂程序员跳槽去小公司当CTO,是一种怎样的体验?
  3. Linux学习(CentOS-7)---磁盘分区(概念、分区方法、分区方案)
  4. Docker中的网络问题
  5. tensorflow 显存 训练_Tensorflow与Keras自适应使用显存方式
  6. Linux下pthread的读写锁的优先级问题
  7. 计算机的发展经历了选择题,计算机发展历程的相关选择题.doc
  8. BN处理较深的神经网络
  9. Android开发 使用HBuilder的缓存方法
  10. Numpy_where
  11. MYSQL索引和权限管理
  12. 5G信令7——Service Request
  13. shell: 脚本获取ssh 端口号
  14. 《MMD》制作极乐净土
  15. uac2+android,iBasso UAC
  16. 51物联卡:物联卡支持5G吗?怎么购买5G物联卡
  17. 爬取雪球网的股票信息评论
  18. springboot二手交易平台 毕业设计-附源码290915
  19. 服务器4块固态硬盘做raid5,固态硬盘内RAID5技术
  20. set接口-存储及遍历、HashSet、LinkedHashSet、TreeSet

热门文章

  1. 系统维护盘Windwos PE的使用
  2. Android GPU 检查器 (AGI)
  3. 飞鸽传输IPMsg协议+翻译
  4. 初读《偷影子的人》观后感
  5. 2021年北京各区高新技术企业认定时间安排,及常见问题解答
  6. vc下文件下载的两种方法
  7. 微信小程序云开发——实现 线上注册,登录的逻辑,并保存账号到云数据库( 三 ):登录
  8. python使用m3u8库解析m3u8文件
  9. 电脑报2013年第9期
  10. 2023认证杯数学建模挑战赛C题心脏危险完整原创论文讲解