jquery的事件命名空间详解
jquery现在的事件API:on,off,trigger支持带命名空间的事件,当事件有了命名空间,就可以有效地管理同一事件的不同监听器,在定义组件的时候,能够避免同一元素应用到不同组件时,同一事件类型之间的影响,还能控制一些意外的事件冒泡。在实际工作中,相信大家都用的很多,但是不一定了解它的所有细节,至少我有这样的经验,经常在碰到疑惑的时候,还得重新写例子去验证它的相关作用,所以本文想把事件命名空间相关的细节都梳理出来,将来再犯迷糊的时候可以回来翻着看看以便加深对它的理解和运用。
在详细了解命名空间之前,得先认识下什么是自定义事件,因为命名空间可以同时应用于自定义事件和浏览器默认事件当中。
1. 自定义事件
我们在定义组件的时候,浏览器的默认事件往往不能满足我们的要求,比如我们写了一个树形组件,它有一个实例方法init用来完成这个组件的初始化工作,在这个方法调用结束之后,我们通常会自定义一个init事件,以便外部可以在树组件初始化完成之后做一些回调处理:
<script src="../js/lib/jquery.js"></script>
<div id="tree"> </div>
<script>
var Tree = function(element, options) {
var $tree = this.$tree = $(element);
//监听init事件,触发
$tree.on('init', $.proxy(options.onInit, this));
this.init();
}; Tree.prototype.init = function() {
console.log('tree init!');
this.$tree.trigger('init');
}; var tree = new Tree('#tree', {
onInit: function() {
console.log(this.$tree.outerHeight());
}
});
</script>
以上代码中.on('init',…)中的init就是一个类似click这样的自定义事件,该代码运行结果如下
自定义事件的使用就跟浏览器默认事件的使用没有任何区别,就连事件冒泡和阻止事件默认行为都完全支持,唯一的区别在于:浏览器自带的事件类型可以通过浏览器的UI线程去触发,而自定义事件必须通过代码来手动触发:

2. 事件命名空间
事件命名空间类似css的类,我们在事件类型的后面通过点加名称的方式来给事件添加命名空间:
<script>
var Tree = function(element, options) {
var $tree = this.$tree = $(element);
//监听init事件,触发
$tree.on('init.my.tree', $.proxy(options.onInit, this));
this.init();
}; Tree.prototype.init = function() {
console.log('tree init!');
this.$tree.trigger('init.my.tree');
}; var tree = new Tree('#tree', {
onInit: function() {
console.log(this.$tree.outerHeight());
}
});
</script>
以上代码中.on('init.my.tree',…)通过.my和.tree给init这个事件添加了2个命名空间,注意命名空间是类似css的类,而不是类似java中的package,所以这两个命名空间的名称分别是.my和.tree,而不是my和my.tree,注意命名空间的名称前面一定要带点,这个名称在off的时候可以用到。在监听和触发事件的时候带上命名空间,当触发带命名空间的事件时,只会调用匹配该命名空间的监听器。所以命名空间可以有效地管理同一事件的不同监听器,尤其在定义组件的时候可以有效地保证组件内部的事件只在组件内部有效,不会影响到其它组件。
现在假设我们不用命名空间,同时定义两个组件Tree和Dragable,并且同时对#tree这个元素做实例化,以便实现一棵可以拖动的树:
<script>
var Tree = function(element, options) {
var $tree = this.$tree = $(element);
//监听init事件,触发
$tree.on('init', $.proxy(options.onInit, this));
this.init();
}; Tree.prototype.init = function() {
console.log('tree init!');
this.$tree.trigger('init');
}; var tree = new Tree('#tree', {
onInit: function() {
console.log(this.$tree.outerHeight());
}
}); var Dragable = function(element, options) {
var $element = this.$element = $(element);
//监听init事件,触发
$element.on('init', $.proxy(options.onInit, this));
this.init();
}; Dragable.prototype.init = function() {
console.log('tree init!');
this.$element.trigger('init');
}; var drag = new Dragable('#tree', {
onInit: function() {
console.log('start drag!');
}
});
</script>
结果会发现Tree的onInit回调被调用两次: 
根本原因就是因为#tree这个元素被应用到了多个组件,在这两个组件内部对#tree这个元素定义了同一个名称的事件,所以后面实例化的组件在触发该事件的时候也会导致前面实例化的组件的同一事件再次被触发。通过命名空间就可以避免这个问题,让组件各自的事件回调互不影响:
<script>
var Tree = function(element, options) {
var $tree = this.$tree = $(element);
//监听init事件,触发
$tree.on('init.my.tree', $.proxy(options.onInit, this));
this.init();
}; Tree.prototype.init = function() {
console.log('tree init!');
this.$tree.trigger('init.my.tree');
}; var tree = new Tree('#tree', {
onInit: function() {
console.log(this.$tree.outerHeight());
}
}); var Dragable = function(element, options) {
var $element = this.$element = $(element);
//监听init事件,触发
$element.on('init.my.dragable', $.proxy(options.onInit, this));
this.init();
}; Dragable.prototype.init = function() {
console.log('drag init!');
this.$element.trigger('init.my.dragable');
}; var drag = new Dragable('#tree', {
onInit: function() {
console.log('start drag!');
}
});
</script>
这样tree实例的onInit就不会被调用2次了:

3. 命名空间的匹配规则
在第2部分的举例当中,触发带命名空间的事件时,触发方式是: 
然后就会调用这里监听的回调:

如果把触发方式改一下,不改监听方式,改成以下三种方式的一种,结果会怎么样呢:
this.$element.trigger('init');
this.$element.trigger('init.dragable');
this.$element.trigger('init.my');
答案是该监听回调依然会被调用。这个跟命名空间的匹配规则有关,为了说明这个规则,可以用以下的这个代码来测试:
<!DOCTYPE html>
<html lang="en">
<head>
<title>xxxxx</title>
<style type="text/css">
#parent {
margin: 100px auto 0 auto;
width: 600px;
height: 200px;
border: 1px solid #ccc;
position: relative;
} .log {
position: absolute;
left: 0;
width: 100%;
height: 100%;
overflow: auto;
} p {
margin: 0;
} #btns {
margin: 20px auto 0 auto;
width: 600px;
}
</style>
</head>
<body>
<script src="../js/lib/jquery.js"></script>
<div id="parent">
<div class="log"></div>
</div>
<div id="btns">
<button id="btn1" type="button" onclick="$p.trigger('click.n1.n2.n3.n4');">trigger('click.n1.n2.n3.n4')</button>
<button id="btn2" type="button" onclick="$p.trigger('click.n1.n2.n3');">trigger('click.n1.n2.n3')</button>
<button id="btn3" type="button" onclick="$p.trigger('click.n1.n2');">trigger('click.n1.n2')</button>
<button id="btn4" type="button" onclick="$p.trigger('click.n1');">trigger('click.n1')</button>
<button id="btn5" type="button" onclick="$p.trigger('click');">trigger('click')</button>
</div>
<script>
function log($e, msg) {
var $log = $e.find('.log');
$log.append('<p>' + msg + '</p>');
} var $p = $('#parent'); $p.on('click.n1.n2.n3.n4', function(){
log($p, 'click n1 n2 n3 n4');
});
$p.on('click.n1.n2.n3', function(){
log($p, 'click n1 n2 n3');
});
$p.on('click.n1.n2', function(){
log($p, 'click n1 n2');
});
$p.on('click.n1', function(){
log($p, 'click n1');
});
$p.on('click', function(){
log($p, 'click');
}); </script>
</body>
</html>
初始化效果如下:
依次点击界面上的按钮(不过点击按钮前得先刷新页面,这样的话各个按钮效果才不会混在一起),界面打印的效果如下:





以上的测试代码一共给$p元素的click事件定义了4个命名空间,然后针对不同的命名空间数量,添加了五个监听器,通过外部的按钮来手动触发各个带命名空间的事件,从最后的结果,我们能得出这样一个规律:
1)当触发不带命名空间的事件时,该事件所有的监听器都会触发;(从最后一个按钮的测试结果可看出)
2)当触发带一个命名空间的事件时,在监听时包含该命名空间的所有监听器都会被触发;(从第4个按钮的测试结果可看出)
3)当触发带多个命名空间的事件时,只有在监听时同时包含那多个命名空间的监听器才会被触发;(从第2,3个按钮的测试结果可看出)
4)只要触发带命名空间的事件,该事件不带命名空间的监听器就不会被触发;(从1,2,3,4个按钮可看出)
5)2跟3其实就是一个,2是3的一种情况
这个规律完全适用于浏览器默认事件和自定义事件,自定义事件的测试可以用下面的代码,结论是一致的:
<!DOCTYPE html>
<html lang="en">
<head>
<title>xxxxx</title>
<style type="text/css">
#parent {
margin: 100px auto 0 auto;
width: 600px;
height: 200px;
border: 1px solid #ccc;
position: relative;
} .log {
position: absolute;
left: 0;
width: 100%;
height: 100%;
overflow: auto;
} p {
margin: 0;
} #btns {
margin: 20px auto 0 auto;
width: 600px;
}
</style>
</head>
<body>
<script src="../js/lib/jquery.js"></script>
<div id="parent">
<div class="log"></div>
</div>
<div id="btns">
<button id="btn1" type="button" onclick="$p.trigger('hello.n1.n2.n3.n4');">trigger('hello.n1.n2.n3.n4')</button>
<button id="btn2" type="button" onclick="$p.trigger('hello.n1.n2.n3');">trigger('hello.n1.n2.n3')</button>
<button id="btn3" type="button" onclick="$p.trigger('hello.n1.n2');">trigger('hello.n1.n2')</button>
<button id="btn4" type="button" onclick="$p.trigger('hello.n1');">trigger('hello.n1')</button>
<button id="btn5" type="button" onclick="$p.trigger('hello');">trigger('hello')</button>
</div>
<script>
function log($e, msg) {
var $log = $e.find('.log');
$log.append('<p>' + msg + '</p>');
} var $p = $('#parent'); $p.on('hello.n1.n2.n3.n4', function(){
log($p, 'hello n1 n2 n3 n4');
});
$p.on('hello.n1.n2.n3', function(){
log($p, 'hello n1 n2 n3');
});
$p.on('hello.n1.n2', function(){
log($p, 'hello n1 n2');
});
$p.on('hello.n1', function(){
log($p, 'hello n1');
});
$p.on('hello', function(){
log($p, 'hello');
}); </script>
</body>
</html>
4. 命名空间的冒泡
为了说明命名空间的冒泡机制,需要把前面的测试代码改一改,并且以自定义事件来说明,测试代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<title>xxxxx</title>
<style type="text/css">
#parent {
margin: 100px auto 0 auto; width: 600px; height: 300px; border: 1px solid #ccc; position: relative;
} #child {
margin: 0 0 0 300px; width: 300px; height: 300px; border: 1px solid #ccc; position: relative;
} .log {
position: absolute; left: 0; width: 100%; height: 100%; overflow: auto;
} p {
margin: 0;
} #btns {
margin: 20px auto 0 auto; width: 600px;
}
</style>
</head>
<body>
<script src="../js/lib/jquery.js"></script>
<div id="parent">
<div class="log"></div>
<div id="child">
<div class="log"></div>
</div>
</div>
<div id="btns">
<button id="btn1" type="button" onclick="$c.trigger('hello.n1.n2.n3.n4');">trigger('hello.n1.n2.n3.n4')</button>
<button id="btn2" type="button" onclick="$c.trigger('hello.n1.n2.n3');">trigger('hello.n1.n2.n3')</button>
<button id="btn3" type="button" onclick="$c.trigger('hello.n1.n2');">trigger('hello.n1.n2')</button>
<button id="btn4" type="button" onclick="$c.trigger('hello.n1');">trigger('hello.n1')</button>
<button id="btn5" type="button" onclick="$c.trigger('hello');">trigger('hello')</button>
</div>
<script>
function log($e, msg) {
var $log = $e.children('.log');
$log.append('<p>' + msg + '</p>');
} var $p = $('#parent'); $p.on('hello.n1.n2.n3.n4', function(){
log($p, 'hello n1 n2 n3 n4');
});
$p.on('hello.n1.n2.n3', function(){
log($p, 'hello n1 n2 n3');
});
$p.on('hello.n1.n2', function(){
log($p, 'hello n1 n2');
});
$p.on('hello.n1', function(){
log($p, 'hello n1');
});
$p.on('hello', function(){
log($p, 'hello');
}); var $c = $('#child'); $c.on('hello.n1.n2.n3.n4', function(){
log($c, 'hello n1 n2 n3 n4');
});
$c.on('hello.n1.n2.n3', function(){
log($c, 'hello n1 n2 n3');
});
$c.on('hello.n1.n2', function(){
log($c, 'hello n1 n2');
});
$c.on('hello.n1', function(){
log($c, 'hello n1');
});
$c.on('hello', function(){
log($c, 'hello');
}); </script>
</body>
</html>
初始化效果如下: 
在这个测试中,点击按钮的时候触发的并不是$p元素的事件,而是$c元素的事件,$p是$c的父元素,上图中整个长方形容器就是$p元素,右边的正方形容器就是$c元素。当我们依次点击上面五个按钮的时候(还是采取刷新一次点一个按钮的方式),界面打印的效果如下:





从这个测试结果来看,我们可以得出一个结论:jquery提供的事件机制,当子元素的带命名空间的事件冒泡到父级元素时,会以同样的命名空间触发父级元素的同一事件,为了方便起见,可以把这种冒泡机制称为带命名空间的冒泡。意味着当子元素的事件冒泡到父级元素时,只有那些满足该事件匹配规则的父级监听器才会被调用。
浏览器默认事件的冒泡也与自定义事件的机制相同,可以用下面的代码测试:
<!DOCTYPE html>
<html lang="en">
<head>
<title>xxxxx</title>
<style type="text/css">
#parent {
margin: 100px auto 0 auto; width: 600px; height: 300px; border: 1px solid #ccc; position: relative;
} #child {
margin: 0 0 0 300px; width: 300px; height: 300px; border: 1px solid #ccc; position: relative;
} .log {
position: absolute; left: 0; width: 100%; height: 100%; overflow: auto;
} p {
margin: 0;
} #btns {
margin: 20px auto 0 auto; width: 600px;
}
</style>
</head>
<body>
<script src="../js/lib/jquery.js"></script>
<div id="parent">
<div class="log"></div>
<div id="child">
<div class="log"></div>
</div>
</div>
<div id="btns">
<button id="btn1" type="button" onclick="$c.trigger('click.n1.n2.n3.n4');">trigger('click.n1.n2.n3.n4')</button>
<button id="btn2" type="button" onclick="$c.trigger('click.n1.n2.n3');">trigger('click.n1.n2.n3')</button>
<button id="btn3" type="button" onclick="$c.trigger('click.n1.n2');">trigger('click.n1.n2')</button>
<button id="btn4" type="button" onclick="$c.trigger('click.n1');">trigger('click.n1')</button>
<button id="btn5" type="button" onclick="$c.trigger('click');">trigger('click')</button>
</div>
<script>
function log($e, msg) {
var $log = $e.children('.log');
$log.append('<p>' + msg + '</p>');
} var $p = $('#parent'); $p.on('click.n1.n2.n3.n4', function(){
log($p, 'click n1 n2 n3 n4');
});
$p.on('click.n1.n2.n3', function(){
log($p, 'click n1 n2 n3');
});
$p.on('click.n1.n2', function(){
log($p, 'click n1 n2');
});
$p.on('click.n1', function(){
log($p, 'click n1');
});
$p.on('click', function(){
log($p, 'click');
}); var $c = $('#child'); $c.on('click.n1.n2.n3.n4', function(){
log($c, 'click n1 n2 n3 n4');
});
$c.on('click.n1.n2.n3', function(){
log($c, 'click n1 n2 n3');
});
$c.on('click.n1.n2', function(){
log($c, 'click n1 n2');
});
$c.on('click.n1', function(){
log($c, 'click n1');
});
$c.on('click', function(){
log($c, 'click');
}); </script>
</body>
</html>
需要特别注意的是:浏览器的默认事件能通过鼠标或键盘等操作,由浏览器UI线程自动触发的,而且只要是浏览器自己触发的事件,是不会带命名空间的。这样的话,只要浏览器在子元素自动触发了默认事件,那么子元素以及父元素所有的监听器都会执行,有时候这并不一定是你期望的,所以最好在开发组件的时候始终加命名空间来触发或者添加监听,这样就能屏蔽掉浏览器自动触发给组件带来的影响。
5. 文中小结
通过第3和第4部分,可以发现jquery的事件机制,纵向是一种带命名空间的冒泡机制,横向是一种按照命名空间匹配规则的管理方式,如下图所示:

综合起来,一个元素上的某个事件监听器如果要被触发的话,一共有以下几种情况:
1)直接在该元素上触发了该事件,通过命名空间匹配规则被触发;
2)由子元素的相关事件冒泡到该元素,再通过匹配规则触发;
3)如果是浏览器默认事件,还会由浏览器自动触发,不过浏览器自动触发最终还是要体现到冒泡规则和匹配规则上来。
6. off方法中的使用
jquery中在移除事件监听的时候,有多种方式,可以不带命名空间只通过事件类型来移除:
$p.off('click');
也可以通过带命名空间的事件类型来移除:
$p.off('click.n1');
还可以只按命名空间来移除:
$p.off('.n1');
为了更清楚地说明这三种移除方式的效果和规律,可以以下代码来测试
<!DOCTYPE html>
<html lang="en">
<head>
<title>xxxxx</title>
<style type="text/css">
#parent {
margin: 100px auto 0 auto; width: 600px; height: 300px; border: 1px solid #ccc; position: relative;
}
.log {
position: absolute; left: 0; width: 100%; height: 100%; overflow: auto;
}
p {
margin: 0;
}
#btns {
margin: 20px auto 0 auto; width: 600px;
}
</style>
</head>
<body>
<script src="../js/lib/jquery.js"></script>
<div id="parent">
<div class="log"></div>
</div>
<div id="btns">
<button id="btn1" type="button" onclick="$p.off('click.n1.n2.n3.n4');">off('click.n1.n2.n3.n4')</button>
<button id="btn2" type="button" onclick="$p.off('click.n1.n2.n3');">off('click.n1.n2.n3')</button>
<button id="btn3" type="button" onclick="$p.off('click.n1.n2');">off('click.n1.n2')</button>
<button id="btn4" type="button" onclick="$p.off('click.n1');">off('click.n1')</button>
<button id="btn5" type="button" onclick="$p.off('click');$p.trigger('hello');">off('click')</button>
<button id="btn6" type="button" onclick="$p.off('.n1.n2.n3.n4');">off('.n1.n2.n3.n4')</button>
<button id="btn7" type="button" onclick="$p.off('.n1.n2.n3');">off('.n1.n2.n3')</button>
<button id="btn8" type="button" onclick="$p.off('.n1.n2');">off('.n1.n2')</button>
<button id="btn9" type="button" onclick="$p.off('.n1');">off('.n1')</button>
</div>
<script>
function log($e, msg) {
var $log = $e.children('.log');
$log.append('<p>' + msg + '</p>');
} var $p = $('#parent'); $p.on('click.n1.n2.n3.n4', function(){
log($p, 'click n1 n2 n3 n4');
});
$p.on('click.n1.n2.n3', function(){
log($p, 'click n1 n2 n3');
});
$p.on('click.n1.n2', function(){
log($p, 'click n1 n2');
});
$p.on('click.n1', function(){
log($p, 'click n1');
});
$p.on('click', function(){
log($p, 'click');
$p.trigger('hello');
}); $p.on('hello.n1.n2.n3.n4', function(){
log($p, 'hello n1 n2 n3 n4');
});
$p.on('hello.n1.n2.n3', function(){
log($p, 'hello n1 n2 n3');
});
$p.on('hello.n1.n2', function(){
log($p, 'hello n1 n2');
});
$p.on('hello.n1', function(){
log($p, 'hello n1');
});
$p.on('hello', function(){
log($p, 'hello');
});
</script>
</body>
</html>
初始化界面效果为: 
在这个测试中,为$p元素的两种事件click和hello各添加了五个监听器,命名空间的的设置还与前面的类似,hello事件在click事件不带命名空间的回调里被触发,提供了9个按钮分别用来测试不同的off事件的方式最后的结果。测试的方法是依次点击按钮(为了不让各个测试的结果互相影响,点击前还是得先刷新页面),点完按钮后,再点击一下$p元素,就是那个灰色边框的容器。只有第五个按钮不需要做第二次$p元素的点击,因为它已经把$p的click事件监听全部移除了,各个按钮的测试结果如下:

结果:click.n1.n2.n3.n4的监听没有被调用,hello事件不受影响。

结果:click.n1.n2.n3.n4和click.n1.n2.n3的监听没有被调用,hello事件不受影响。

结果:click.n1.n2.n3.n4和click.n1.n2.n3和click.n1.n2的监听没有被调用,hello事件不受影响。

结果:click.n1.n2.n3.n4和click.n1.n2.n3和click.n1.n2和click.n1的监听没有被调用,hello事件不受影响。

结果:所有click事件的回调都没有调用,hello事件不受影响。
综合以上的测试结果,可以得出的结论是:
1)当通过一个或多个命名空间结合事件类型来移除的时候,只会把该事件的在添加监听的时候包含那些命名空间的监听器移除,不会影响该事件类型的其它监听器以及其它事件类型。比如移除click.n1.n2,会把click.n1.n2,click.n1.n2.n3还有click.n1.n2.n3.n4都移除,但是click.n1 , click 还有hello事件都不受影响。
2)当通过事件类型来移除的时候,会把该事件的所有监听器都移除。
再看从第6个按钮开始的测试:

结果:移除了click.n1.n2.n3.n4和hello.n1.n2.n3.n4,其它事件监听不受影响。

结果:移除了click.n1.n2.n3.n4,click.n1.n2.n3和hello.n1.n2.n3.n4,hello.n1.n2.n3,其它事件监听不受影响。

结果:移除了click.n1.n2.n3.n4,click.n1.n2.n3,click.n1.n2和hello.n1.n2.n3.n4,hello.n1.n2.n3,hello.n1.n2,其它事件监听不受影响。

结果:移除了hello和click事件所有的带命名空间的监听。
综合最后这部分的测试结果,可以得出的结论是:
通过命名空间移除监听的时候,会影响所有的事件类型,会把所有事件类型的在添加监听的时候包含那些命名空间的监听器全部移除掉。比如最后的off(.n1),就把click和hello事件的所有带.n1这个命名空间的监听移除掉了。
7. 本文小结
本文花了大量的测试去了解命名空间在事件触发和事件冒泡以及移除监听时候的特性,内容虽然非常之多,但是已经充分达到了本文的最终目的,就是要把命名空间在事件管理里面的细节都梳理清楚,文中各个部分的核心内容最后都有简短的结论,将来有需要的时候可以直接通过结论来解除自己的疑惑,希望能给大家带来一些帮助,谢谢阅读:)
jquery的事件命名空间详解的更多相关文章
- jQuery常用事件方法详解
目录 jQuery事件 ready(fn)|$(function(){}) jQuery.on() jQuery.click jQuery.data() jQuery.submit() jQuery事 ...
- jQuery 事件用法详解
jQuery 事件用法详解 目录 简介 实现原理 事件操作 绑定事件 解除事件 触发事件 事件委托 事件操作进阶 阻止默认事件 阻止事件传播 阻止事件向后执行 命名空间 自定义事件 事件队列 jque ...
- 触碰jQuery:AJAX异步详解
触碰jQuery:AJAX异步详解 传送门:异步编程系列目录…… 示例源码:触碰jQuery:AJAX异步详解.rar AJAX 全称 Asynchronous JavaScript and XML( ...
- jQuery调用AJAX异步详解[转]
AJAX 全称 Asynchronous JavaScript and XML(异步的 JavaScript 和 XML).它并非一种新的技术,而是以下几种原有技术的结合体. 1) 使用CSS和X ...
- jQuery的deferred对象详解(一)
最近一段时间,都在研究jquery里面的$.Deffered对象,几天都搞不明白,其中源码的运行机制,网上查找了相关的资料,<jQuery的deferred对象详解>阮一峰老师的文章,里面 ...
- 触碰jQuery:AJAX异步详解(转)
AJAX 全称 Asynchronous JavaScript and XML(异步的 JavaScript 和 XML).它并非一种新的技术,而是以下几种原有技术的结合体. 1) 使用CSS和X ...
- jQuery form插件使用详解
点击打开: jquery选择器全解 jquery中的style样式操作 jquery中的DOM操作 jquery中的事件操作全解 jquery中的动画操作全解 jquery中ajax的应用 自定义jq ...
- [转] jQuery的deferred对象详解
jQuery的开发速度很快,几乎每半年一个大版本,每两个月一个小版本. 每个版本都会引入一些新功能.今天我想介绍的,就是从jQuery 1.5.0版本开始引入的一个新功能----deferred对象. ...
- jQuery的deferred对象详解(转)
jQuery的开发速度很快,几乎每半年一个大版本,每两个月一个小版本. 每个版本都会引入一些新功能.今天我想介绍的,就是从jQuery 1.5.0版本开始引入的一个新功能----deferred对象. ...
随机推荐
- Remote Desktop Connection Manager
通过Remote Desktop Connection Manager(RDCMan),当前最新版本是 v2.7. 通过这款软件,我们便可以轻松的管理和访问数个RDP.左边的列表中我们可以创建总的分区 ...
- ASP.NET Web API 接口执行时间监控
软件产品常常会出现这样的情况:产品性能因某些无法预料的瓶颈而受到干扰,导致程序的处理效率降低,性能得不到充分的发挥.如何快速有效地找到软件产品的性能瓶颈,则是我们感兴趣的内容之一. 在本文中,我将解释 ...
- Hadoop学习笔记—8.Combiner与自定义Combiner
一.Combiner的出现背景 1.1 回顾Map阶段五大步骤 在第四篇博文<初识MapReduce>中,我们认识了MapReduce的八大步凑,其中在Map阶段总共五个步骤,如下图所示: ...
- 一个App完成入门篇(六)- 完成通讯录页面
第五章和第六章间隔时间有点长,对不起大家了.下面继续. 本节教程将要教会大家如何加载本地通讯录. 导入项目 导入通讯录 自定义js模块 发送和订阅page消息 将要学习的demo效果图如下所示 1. ...
- ASP.NET MVC SSO单点登录设计与实现
实验环境配置 HOST文件配置如下: 127.0.0.1 app.com127.0.0.1 sso.com IIS配置如下: 应用程序池采用.Net Framework 4.0 注意IIS绑定的域名, ...
- Step by step Install a Local Report Server and Remote Report Server Database
原创地址:http://www.cnblogs.com/jfzhu/p/4012097.html 转载请注明出处 前面的文章<Step by step SQL Server 2012的安装 &g ...
- iOS 代码规范
1 目的 统一规范XCode编辑环境下Objective-C.swift的编码风格和标准 2 适用范围 适用于所有用Objective-C,swift语言开发的项目. 3 编码规范 3.1 文件 项目 ...
- 网页webp转非webp的jpg gif png 图片
webp 谷歌提出的一种图片格式.支持动图: gif静图: png jpg 网页 webp / jpg / gif / png 图片提取. 已在微信.淘宝.京东.一号店上测试通过. 如果电脑上有 ch ...
- 把w3schools英文版的所有属性扒下来了,免费分享。
为了方便查手册等,把w3schools上的所以属性弄成json版的了,到时候再修改一下,查起来就比较方便了,这里免费分享一下.一共为两份,一份为选择器部分,还有一部分是属性. 选择器部分json 属性 ...
- Sql Server系列:嵌套查询
嵌套查询是指一个查询语句嵌套在另一个查询语句内部的查询.嵌套查询也就子查询,在SELECT子句中先计算子查询,子查询结果作为外层另一个查询的过滤条件,查询可以基于一个表或多个表.子查询中可以使用比较运 ...