前言

最近好好的研究了一番移动设备的点击响应速度,期间不断的被自己坑,最后搞得焦头烂额,就是现在可能还有一些问题,但是过程中感觉自己成长不少,

最后居然感觉对javascript事件机制有了更好的认识,回头来看,还是不错的,所以今天将近期的学习记录下来供后期查询

今天我们再来重新回顾下javascript的事件机制

注意:下面说的android浏览器,意思是android下多数浏览器,不包括chrome

事件基础

javascript与html之间的交互式通过事件实现的,事件是文档(窗口)中发生的一些特定交互,这些交互可以使用监听器(处理程序)预定,事件发生时就会回调我们的函数

PS:这就是传说中的观察者模式,我们这里先不管他

因为我们需要确定页面哪一部分会拥有特定事件,比如内部一个span外部一个div,我们点击span时候事实上浏览器也任务div被点击了,甚至整个document也被点击了,所以引入了事件流的概念

事件流是描述从页面接收事件的顺序,现在统一有事件冒泡与事件捕获两种事件捕获流

事件冒泡/捕获

事件冒泡即由最具体的元素(文档嵌套最深节点)接收,然后逐步上传至document

事件捕获会由最先接收到事件的元素然后传向最里边(我们可以将元素想象成一个盒子装一个盒子,而不是一个积木堆积)

DOM事件流

DOM2级事件规定事件包括三个阶段:

① 事件捕获阶段

② 处于目标阶段

③ 事件冒泡阶段

所以说,我们同时为一个元素绑定事件(冒泡与捕获)先执行的是捕获,然后会执行冒泡

 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<style type="text/css">
#p { width: 300px; height: 300px; padding: 10px; border: 1px solid black; }
#c { width: 100px; height: 100px; border: 1px solid red; }
</style>
</head>
<body>
<div id="p">
parent
<div id="c">
child
</div>
</div>
<script type="text/javascript">
var p = document.getElementById('p'),
c = document.getElementById('c');
c.addEventListener('click', function () {
alert('子节点捕获')
}, true); c.addEventListener('click', function () {
alert('子节点冒泡')
}, false);
</script>
</body>
</html>

这个样子点击子元素会先执行捕获阶段注册的事件,然后执行冒泡阶段执行的事件,我们这里做一点改变

 var p = document.getElementById('p'),
c = document.getElementById('c');
c.addEventListener('click', function () {
alert('子节点捕获')
}, true); c.addEventListener('click', function () {
alert('子节点冒泡')
}, false); p.addEventListener('click', function () {
alert('父节点捕获')
}, true); p.addEventListener('click', function () {
alert('父节点冒泡')
}, false);

① 这个时间点击父元素会先执行父元素捕获再执行父元素冒泡

② 点击子元素会执行父元素捕获,子元素捕获,子元素冒泡,父元素冒泡

至此,我们对事件流机制应该了解一些了,于是继续往下(注意:此点知识与“鬼点击”有莫大的关系)

事件对象

事件就是用户或浏览器自身执行的某种动作(click、load),响应事件的函数就是事件处理程序(监听器)

而我们的事件往往会自带一个参数——事件对象(IE那劳什子就不管了)

 c.addEventListener('click', function (e) {
alert('子节点捕获')
}, true);

注意我们的e,他就是我们的event object了

事件对象,包含和创建他的特定事件有关的属性和方法,触发的事件不一样,参数也不一样(比如鼠标事件就会有坐标信息),我们这里题几个较重要的

PS:以下的兄弟全部是只读的,所以不要妄想去随意更改

bubbles

表明事件是否冒泡

cancelable

表明是否可以取消事件的默认行为

currentTarget

某事件处理程序当前正在处理的那个元素

defaultPrevented

为true表明已经调用了preventDefault(DOM3新增)

eventPhase

调用事件处理程序的阶段:1 捕获;2 处于阶段;3 冒泡阶段

target

事件目标(绑定事件那个dom)

trusted

true表明是系统的,false为开发人员自定义的(DOM3新增)

type

事件类型

view

与事件关联的抽象视图,发生事件的window对象

preventDefault

取消事件默认行为,cancelable是true时可以使用

stopPropagation

取消事件捕获/冒泡,bubbles为true才能使用

stopImmediatePropagation

取消事件进一步冒泡,并且组织任何事件处理程序被调用(DOM3新增)

在我们的事件处理内部,this与currentTarget相同

思考事件参数

这里有一个比较有意思的问题,说他有意思,是因为我觉得可能各位平时没有思考过:

我们一次点击事件,各个事件处理的Event Object是否相同?

答案是肯定的,这里我们用IE的事件对象来说,我们是这样获得的window.event,IE这样干不是没有道理的,因为我们一次点击这个家伙是共用的!!!

事实上,我们每次鼠标操作,这个事件参数都是相同的,不信??

以PC来说,我们为movedown绑定一个事件,并且动态为e增加一个属性,newArg

 window.log = function (msg) {
console.log(msg)
} var p = document.getElementById('p'),
c = document.getElementById('c'); document.addEventListener('click', function (e) {
e.newArg = '叶小钗';
}, true); c.addEventListener('click', function (e) {
log(e);
log('子节点捕获')
}, true); c.addEventListener('click', function (e) {
log(e);
log('子节点冒泡')
}, false); p.addEventListener('click', function (e) {
log(e);
log('父节点捕获')
}, true); p.addEventListener('click', function (e) {
log(e);
log('父节点冒泡')
}, false);

在最后的事件冒泡阶段,我们可以看到,我们是多了一个newArg属性的,由此我们可以证明我们整个过程中event是一样的

模拟事件

事件,就是网页中某个值得关注的瞬间,事件经常由用户操作或浏览器功能触发,其实我们可以使用javascript在任意时刻来触发特定事件

而,此时的事件就和浏览器创建的事件一样,也就是说我们的事件会冒泡会导致浏览器默认行为触发,模拟事件是出现鬼点击主要原因

createEvent

可以在document对象上使用createEvent创建一个event对象

DOM3新增以下事件:
UIEvents
MouseEvents
MutationEvents,一般化dom变动
HTMLEvents一般dom事件

模拟鼠标事件

创建鼠标事件时需要创建的事件对象需要提供指定的信息(鼠标位置信息),我们这里提供以下参数:

var type = 'click'; //要触发的事件类型
var bubbles = true; //事件是否可以冒泡
var cancelable = true; //事件是否可以阻止浏览器默认事件
var view = document.defaultView; //与事件关联的视图,该属性默认即可,不管
var detail = 0;
var screenX = 0;
var screenY = 0;
var clientX = 0;
var clientY = 0;
var ctrlKey = false; //是否按下ctrl
var altKey = false; //是否按下alt
var shiftKey = false;
var metaKey = false;
var button = 0;//表示按下哪一个鼠标键
var relatedTarget = 0; //模拟mousemove或者out时候用到,与事件相关的对象 var event = document.createEvent('MouseEvents');
event.initMouseEvent(type, bubbles, cancelable, view, detail, screenX, screenY, clientX, clientY,
ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget);

如此我们就可以用到这个东西了,好了,我们后面会用到他的,至此,我们基础复习完毕,进入今天的正题吧

“鬼点击”何来

我们一般的移动设备在浏览网页时候都会有这样的功能:连续点击两次页面,整个页面会放大!

这是我们click事件在移动端会延迟300ms的主要原因

但是,我们真正开发移动站点时候,会限制我们的viewport,所以双击放大的效果便没有意义,这个效果反而让我们整个网页看起来“迟钝”

而我们的touch事件并不会有任何延迟,所以他就成了我们解决click响应速度的利刃,而且我也暂时只知道他能干(chrome30更新后,解决了这个问题)

所以javascript提出了几个解决方案, 第一个方案当然是我们的tap事件

tap事件

tap事件的由来是系统自建了一个事件,叫做tap事件,他在touchend时候会触发

PS:复杂的判断逻辑我们这里就不写了

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<style type="text/css">
#p { width: 300px; height: 300px; padding: 10px; border: 1px solid black; }
#c { width: 100px; height: 100px; border: 1px solid red; }
</style>
</head>
<body>
<input id="tap" type="button" value="我是tap" /><br />
<input id="click" type="button" value="我是click" />
<script type="text/javascript">
var tap = document.getElementById('tap');
var click = document.getElementById('click');
var t = 0, el; document.addEventListener('touchstart', function (e) {
t = e.timeStamp;
el = e.target;
});
document.addEventListener('touchend', function (e) {
t = e.timeStamp;
var type = 'tap'; //要触发的事件类型
var bubbles = true; //事件是否可以冒泡
var cancelable = true; //事件是否可以阻止浏览器默认事件
var view = document.defaultView; //与事件关联的视图,该属性默认即可,不管
var detail = 0;
var screenX = 0;
var screenY = 0;
var clientX = 0;
var clientY = 0;
var ctrlKey = false; //是否按下ctrl
var altKey = false; //是否按下alt
var shiftKey = false;
var metaKey = false;
var button = 0; //表示按下哪一个鼠标键
var relatedTarget = 0; //模拟mousemove或者out时候用到,与事件相关的对象
var event = document.createEvent('MouseEvents');
event.initMouseEvent(type, bubbles, cancelable, view, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget);
//触发tap事件
el.dispatchEvent(event);
});
function fnDom(el, msg, e) {
el.value = msg + '(' + (e.timeStamp - t) + ')';
}
tap.addEventListener('tap', function (e) {
fnDom(this, '我是tap,我响应时间:', e);
});
click.addEventListener('click', function (e) {
fnDom(this, '我是click,我响应时间:', e);
});
</script>
</body>
</html>

这里的响应时间计算可能有点夸张,但是各位用手机浏览器打开点击后应该会有感觉:

http://sandbox.runjs.cn/show/ljqf8gah

测试过的朋友会发现明显的顺畅感和堵塞感,然后我们来看看如何改写本身事件:

鬼点击之因

我们的项目可能已经做过一半了,也许我们的项目已经完成,所以,我们并不想将click事件一个个换成tap,谁知道tap会出什么劳什子问题!

PS:事实上tap确实搞了不少事情出来

所以,我们想到了改写click事件触发点,直接全站提升click的响应速度,于是我们将上面的代码这样一改

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<style type="text/css">
#p { width: 300px; height: 300px; padding: 10px; border: 1px solid black; }
#c { width: 100px; height: 100px; border: 1px solid red; }
</style>
</head>
<body>
<input id="tap1" type="button" value="我是tap" /><br />
<input id="click1" type="button" value="我是click" /> <script type="text/javascript">
var tap1 = document.getElementById('tap1');
var click1 = document.getElementById('click1');
var t = 0, el; document.addEventListener('touchstart', function (e) {
t = e.timeStamp;
el = e.target;
}); //注意,此处鼠标信息我没有管他
function createEvent(type) {
var bubbles = true; //事件是否可以冒泡
var cancelable = true; //事件是否可以阻止浏览器默认事件
var view = document.defaultView; //与事件关联的视图,该属性默认即可,不管
var detail = 0;
var screenX = 0;
var screenY = 0;
var clientX = 0;
var clientY = 0;
var ctrlKey = false; //是否按下ctrl
var altKey = false; //是否按下alt
var shiftKey = false;
var metaKey = false;
var button = 0; //表示按下哪一个鼠标键
var relatedTarget = 0; //模拟mousemove或者out时候用到,与事件相关的对象
var event = document.createEvent('MouseEvents');
event.initMouseEvent(type, bubbles, cancelable, view, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget);
return event;
}
document.addEventListener('touchend', function (e) {
t = e.timeStamp; var event = createEvent('tap')
//触发tap事件
el.dispatchEvent(event); //触发click
var cEvent = createEvent('click');
el.dispatchEvent(cEvent);
});
function fnDom(el, msg, e) {
el.value = msg + '(' + (e.timeStamp - t) + ')';
}
tap1.addEventListener('tap', function (e) {
fnDom(this, '我是tap,我响应时间:', e);
});
click1.addEventListener('click', function (e) {
fnDom(this, '我是click,我响应时间:', e);
});
</script>
</body>
</html>

http://sandbox.runjs.cn/show/8ruv88rb

这里我们点击按钮后就明显看到了按钮开始响应时间是80左右,马上变成了300多ms,因为click事件被执行了两次

一次是touchend我们手动执行,一次是系统自建的click,这就是传说中的鬼点击

初步解决鬼点击

起初,我认为解决鬼点击比较简单:直接在touchend处阻止浏览器默认事件即可:

 document.addEventListener('touchend', function (e) {
t = e.timeStamp; var event = createEvent('tap')
//触发tap事件
el.dispatchEvent(event); //触发click
var cEvent = createEvent('click');
el.dispatchEvent(cEvent); e.preventDefault(); });

按道理来说,这个代码是没有问题的(而且同时可以解决我们的点透问题),但是在android上情况有所不同

我们的click依旧执行了两次!!!!!不信,您去试试......

PS:不要问我为什么android不行,我这个事情没搞透,如果您知道,请给我留言

现在回到我们最初(昨天吧,自己做的demo)的例子:

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<style type="text/css">
.bt { position: absolute; top: 250px; display: block; height: 50px; }
</style>
</head>
<body>
<input type="button" class="bt" value="我是快速点击事件" id="fastclick" />
<input type="text" style="width: 150px; height: 200px;" />
<div id="div" style="width: 200px; height: 200px; border: 1px solid black">
</div>
</body>
<script type="text/javascript">
var fastclick = document.getElementById('fastclick');
var div = document.getElementById('div');
var touch = {};
var t = new Date().getTime(); window.log = function (msg) {
var d = document.createElement('div');
d.innerHTML = msg;
div.appendChild(d);
console.log(msg);
}; document.addEventListener('click', function (event) {
if (event.myclick == true) {
return true;
}
if (event.stopImmediatePropagation) {
event.stopImmediatePropagation();
} else {
event.propagationStopped = true;
}
event.stopPropagation();
event.preventDefault();
return true;
}, true); document.addEventListener('touchstart', function (e) {
touch.startTime = e.timeStamp;
touch.el = e.target;
t = e.timeStamp;
});
document.addEventListener('touchmove', function (e) { });
document.addEventListener('touchend', function (e) {
touch.last = e.timeStamp;
var event = document.createEvent('Events');
event.initEvent('click', true, true, window, 1, e.changedTouches[0].screenX, e.changedTouches[0].screenY, e.changedTouches[0].clientX, e.changedTouches[0].clientY, false, false, false, false, 0, null);
event.myclick = true;
touch.el && touch.el.dispatchEvent(event);
return true;
}); function fnDom(el, msg, e) {
el.value = msg + '(' + (e.timeStamp - t) + ')';
el.style.display = 'none';
setTimeout(function () {
el.style.display = '';
}, 1000)
} fastclick.addEventListener('click', function (e) {
fnDom(this, '我是快速点击事件', e);
log('快速点击');
}); div.addEventListener('click', function (e) {
this.innerHTML += 'div<br/>'
});
</script>
</html>

http://sandbox.runjs.cn/show/muk6q2br

最后追寻很久找到一个解决方案,该方案将上述知识点全部联系起来了:

① 我们程序逻辑时先触发touch事件,在touchend时候模拟click事件

② 这时我们给click事件对象一个属性:

 var event = document.createEvent('Events');
event.initEvent('click', true, true, window, 1, e.changedTouches[0].screenX,
e.changedTouches[0].screenY, e.changedTouches[0].clientX, e.changedTouches[0].clientY, false, false, false, false, 0, null);
event.myclick = true;
touch.el && touch.el.dispatchEvent(event);

③ 然后按照我们基础篇的逻辑,我们事实上会先执行document上的click事件

我们这里做了一个操作,判断是否包含myclick属性,有就直接跳出(事件会向下传递),如果没有就阻止传递

到此,我们就解决了鬼点击问题,当然,不够完善

点透问题

我们如果刚刚点击按钮时候让按钮消失,事实上他会触发在他下面元素的click事件!

这个就是我们所谓“点透”问题,这个点透可以通过解决鬼点击的方式解决,但是有一种点透却不是那么简单的!!!

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<style type="text/css">
.bt { position: absolute; top: 50px; display: block; height: 50px; }
</style>
</head>
<body>
<input type="button" class="bt" value="我是快速点击事件" id="fastclick" />
<input type="text" style="width: 150px; height: 200px;" />
<div id="div" style="width: 200px; height: 200px; border: 1px solid black">
</div>
</body>
<script type="text/javascript">
var fastclick = document.getElementById('fastclick');
var div = document.getElementById('div');
var touch = {};
var t = new Date().getTime(); window.log = function (msg) {
var d = document.createElement('div');
d.innerHTML = msg;
div.appendChild(d);
console.log(msg);
}; document.addEventListener('click', function (event) {
if (event.myclick == true) {
return true;
}
if (event.stopImmediatePropagation) {
event.stopImmediatePropagation();
} else {
event.propagationStopped = true;
}
event.stopPropagation();
event.preventDefault();
return true;
}, true); document.addEventListener('touchstart', function (e) {
touch.startTime = e.timeStamp;
touch.el = e.target;
t = e.timeStamp;
});
document.addEventListener('touchmove', function (e) { });
document.addEventListener('touchend', function (e) {
touch.last = e.timeStamp;
var event = document.createEvent('Events');
event.initEvent('click', true, true, window, 1, e.changedTouches[0].screenX, e.changedTouches[0].screenY, e.changedTouches[0].clientX, e.changedTouches[0].clientY, false, false, false, false, 0, null);
event.myclick = true;
touch.el && touch.el.dispatchEvent(event);
return true;
}); function fnDom(el, msg, e) {
el.value = msg + '(' + (e.timeStamp - t) + ')';
el.style.display = 'none';
setTimeout(function () {
el.style.display = '';
}, 1000)
} fastclick.addEventListener('click', function (e) {
fnDom(this, '我是快速点击事件', e);
log('快速点击');
}); div.addEventListener('click', function (e) {
this.innerHTML += 'div<br/>'
});
</script>
</html>

这种情况下,我们点击按钮,按钮消失,然后下面的input会获取焦点的!这个问题无法避免,解决方案依旧是阻止浏览器本身事件

这样在ios下面就没有问题了,当然现在我们input不能获得焦点了,但是该问题比较简单,我们暂时不管他,说下我们android下的问题

现在我们在android下,那个input非要获得焦点,这就是我们最痛恨的“点透”现象之一

该种场景比较常见:我们点击按钮出现一个弹出层,我们点击弹出层关闭按钮,正好下面有个input标签,尼玛就谈了一个键盘出来......

android问题

最后研究得出了惊人的结果,这个劳什子android里面moveover事件偶然比尼玛touchstart还快!!!

而ios压根就不理睬mouseover事件,这是主要问题产生原因!!!

而android在movedown时候,开开心心触发了input的focus事件,然后键盘就弹起来了!!!

所以针对android,我们还得将mousedown干掉才行!!!!

而事实上,我们input获取焦点,就是通过mousedown触发的,ios也是

至此,我们主要问题讨论的差不多了,暂时到这里吧。

结语

今天我们一起温故了一次javascript事件相关的知识,记录了最近我遇到的一些问题供以后查询,如果这些知识对你有用就善莫大焉了

【初窥javascript奥秘之事件机制】论“点透”与“鬼点击”的更多相关文章

  1. JavaScript 详说事件机制之冒泡、捕获、传播、委托

    DOM事件流(event  flow )存在三个阶段:事件捕获阶段.处于目标阶段.事件冒泡阶段. 事件捕获(event  capturing):通俗的理解就是,当鼠标点击或者触发dom事件时,浏览器会 ...

  2. javascript 中的事件机制

    1.javascript中的事件. 事件流 javascript中的事件是以一种流的形式存在的. 一个事件会也有多个元素同时响应. 有时候这不是我们想要的效果, 我们只是需要某个特定的元素相应我们的绑 ...

  3. javascript之-深入事件机制

    作者:yuyuyu链接:https://zhuanlan.zhihu.com/p/24620643来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 1.1 事件绑定的方式 ...

  4. windows内核初窥(二)-----系统机制

    系统机制: windows2000为执行体.内核.设备驱动程序等核心态部分提供了一些基础机制.先让我们看看都有哪些: (1)陷阱调度:包括中断.延迟过程调用(DPC).异步过程调用(APC).异常处理 ...

  5. 初窥Javascript单元测试,附带掌握一门新技能的学习方式。

    之前没感觉要学啥单元测试,项目中测试都是手动测的,但也没觉的啥,但最近看文章和招聘上也多多少少有这方面的需求,于是网上搜索了一下,只找到了一些文章,但介绍的都不是很详细或者说比较复杂,满满的伤,虽然看 ...

  6. jQuery中的事件机制深入浅出

    昨天呢,我们大家一起分享了jQuery中的样式选择器,那么今天我们就来看一下jQuery中的事件机制,其实,jQuery中的事件机制与JavaScript中的事件机制区别是不大的,只是,JavaScr ...

  7. JavaScript(1)---绑定事件、解除绑定事件

    JavaScript(1)---绑定事件.解除绑定事件 一.事件概述 1.事件的几个概念 · 事件 指的是文档或者浏览器窗口中发生的一些特定交互瞬间.我们可以通过侦听器(或者处理程序)来预定事件,以便 ...

  8. 【移动端兼容问题研究】javascript事件机制详解(涉及移动兼容)

    前言 这篇博客有点长,如果你是高手请您读一读,能对其中的一些误点提出来,以免我误人子弟,并且帮助我提高 如果你是javascript菜鸟,建议您好好读一读,真的理解下来会有不一样的收获 在下才疏学浅, ...

  9. [解惑]JavaScript事件机制

    群里童鞋问到关于事件传播的一个问题:“事件捕获的时候,阻止冒泡,事件到达目标之后,还会冒泡吗?”. 初学 JS 的童鞋经常会有诸多疑问,我在很多 QQ 群也混了好几年了,耳濡目染也也收获了不少,以后会 ...

随机推荐

  1. 实现CSS等分布局的4种方式

    × 目录 [1]float [2]inline-block [3]table[4]flex 前面的话 等分布局是指子元素平均分配父元素宽度的布局方式,本文将介绍实现等分布局的4种方式 思路一: flo ...

  2. Hadoop官方文档翻译——YARN Architecture(2.7.3)

    The fundamental idea of YARN is to split up the functionalities of resource management and job sched ...

  3. Hadoop官方文档翻译——MapReduce Tutorial

    MapReduce Tutorial(个人指导) Purpose(目的) Prerequisites(必备条件) Overview(综述) Inputs and Outputs(输入输出) MapRe ...

  4. HTML5移动Web开发(五)——移动设计之CSS媒介查询

    CSS媒介查询(media query)是响应式设计中很重要的部分,它帮助你实现更加灵活的移动设计. 看示例代码ch01r06_c.html <!doctype html> <htm ...

  5. [转载]TFS测试管理

    微软2010年发布的Visual Studio 2010或Visual Studio Test Professional 2010包含一个称为 Microsoft 测试管理器的新应用程序,用于帮助您使 ...

  6. CSS SANS – 神奇!使用 CSS3 创建的字体

    在我们的认识中,CSS 所能做的就是改变网页的排版布局,调整字间距等.然而,这里我们要介绍的则是使用 CSS3 制作字体.CSS SANS 可以通过 CSS 技术创建的A-Z字体,一起来围观下. 在线 ...

  7. Dagger2 生成代码学习

    接上一篇文章介绍了Dagger2的初步使用,相信刚接触的人会觉得很奇怪,怎么会有很多自己没有定义的代码出现,为什么Component的创建方式是那样的.为了搞清楚这些东西,我们需要查看一下Dagger ...

  8. 意译:《JVM Internals》

    译者语 为加深对JVM的了解和日后查阅时更方便,于是对原文进行翻译.内容是建立在我对JVM的认识的基础上翻译的,加上本人的英语水平有限,若有纰漏请大家指正,谢谢. 原文地址:http://blog.j ...

  9. js限制文本框只可以输入数字

    封装了一下,要用的话直接调用下面getEvent函数即可   function getEvent() { if (document.all) { return window.event; //for ...

  10. ORLEANS REMOTE DEPLOYMENT

    Orleans Remote Deployment Table of Contents Overview: 1 Prerequisites. 2 Deployment Steps. 2 Orleans ...