转入新的公司的最初这段时间在备课。当老师果然任重道远,再基础的知识也要细致的梳理。准备前端的时候把jQuery的learning center的文章大体看了下,有些新发现,跟大家分享。

jQuery是个啥?

以前就知道它是个很强大的框架,大家都在用。这次发现其实jQuery是个封装版本的js。js不好用的api,他都拿来封装下,再加上程序员的智慧,提供简洁方便的命名和编程方式(比如,chaining)。所以,他不能归类为某个领域,他跟js在同一个领域,啥都可以搞。

事件冒泡和事件委托

以前经常遇到一个问题,就是新创建的元素插入到dom中事件就不管用啦,为啥呢?怎么解决呢?含含糊糊这么多年。其实jquery的事件绑定只在它执行的那个瞬间有用,之后添加的是没有的。聪明的john就想到了事件冒泡(event bubling/ event propagation),也就是某个元素的事件被触发以后,事件会向上冒泡,给到他的parent,如此往上直到document root。

  • <a>
  • <li>
  • <ul #list>
  • <div #container>
  • <body>
  • <html>
  • document root

所以,某个元素被点击,就等于他的祖先也会被点击,那么如果监听其parent的点击事件,然后确认是那个孩子惹得祸,就能解决如上的问题了。jQuery 1.7+的方案如下,#list是parent,其下的某个子节点是<a>标签。这就可以说明为,#list下的某个a标签被点击了,不是指向具体的标签了。问题迎刃而解。

1
2
3
4
5
// Attach a delegated event handler
$( "#list" ).on( "click", "a", function( event ) {
event.preventDefault();
console.log( $( this ).text() );
});

自定义事件用于解耦

如下html片段

1
2
3
4
5
6
&lt;div class="room" id="kitchen"&gt;
&lt;div class="lightbulb on"&gt;&lt;/div&gt;
&lt;div class="switch"&gt;&lt;/div&gt;
&lt;div class="switch"&gt;&lt;/div&gt;
&lt;div class="clapper"&gt;&lt;/div&gt;
&lt;/div&gt;

一个厨房有个灯(.lightbulb)和几个开关(.switch .clapper),现在要开关灯。两种实现方案:

1
2
3
4
5
6
7
8
$( ".switch, .clapper" ).click(function() {
var light = $( this ).closest( ".room" ).find( ".lightbulb" );
if ( light.is( ".on" ) ) {
light.removeClass( "on" ).addClass( "off" );
} else {
light.removeClass( "off" ).addClass( "on" );
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
$( ".lightbulb" ).on( "light:toggle", function( event ) {
var light = $( this );
if ( light.is( ".on" ) ) {
light.removeClass( "on" ).addClass( "off" );
} else {
light.removeClass( "off" ).addClass( "on" );
}
});

$( ".switch, .clapper" ).click(function() {
var room = $( this ).closest( ".room" );
room.find( ".lightbulb" ).trigger( "light:toggle" );
});

后一种方案创建了一个自定义的light:toggle事件,将事件的触发和处理代码解耦。而且事件处理代码可以复用。这里是一个消费与订阅的模型,也就是事件编程的基本模型。

事实证明,阅读官方文档非常有必要。 不过jQuery的文档不像写给纯新手看的,要有点基础才得行,而且没有中文。但是看懂实在很爽。