首页 > 代码库 > jQuery几个易混淆之处(参考《众妙之门》及相关博客)

jQuery几个易混淆之处(参考《众妙之门》及相关博客)

parent() && parents() && closest()

这三个方法都与沿着DOM向上导航有关,在由选择器返回的元素上方,匹配父元素或之前的祖先元素,但是每个方法都有各自独特之处:

1.  parent()

只匹配元素的直接父元素,他可以带一个选择器做参数,对于匹配符合某些条件的父元素非常有用。例如:

$(‘span#mySpan’).parent().css(‘background’, ‘red’);

$(‘p’).parent(‘div.large’).css(background’, ‘red’);

第一行给出元素#mySpan的父元素。第二行对所有的<p>标记的父元素进行同样的处理,假设父元素是div并具有large类。

提示:

像第二行中限制方法的范围是jQuery的常见功能,大多数DOM操作方法都可以让你像这样指定选择器,这不是parent()方法独有的。

 

2. parents()

这个方法不仅限于匹配元素的上一层,也就是说他可以返回多个祖先元素,例如:

$(‘li.nav’).parents(‘li’);

这就是说,对于每个包含nav类的<li>,都会返回同样是<li>的父元素或祖先元素;

3.  closest()

它的作用很像parents,只不过他只返回一个父元素或祖先元素。

提示:你也可以通过使用parents()并限制其只返回一个元素来代替closest():

$($(‘#element1’).parents(‘#element2’).get(0)).css(‘background’, ‘red’);

关于closest()特别要注意点的一点是,他从选择器匹配的元素---而不是父元素开始遍历,这意味着如果传入closest()的选择器匹配当前操作的元素,他将会返回自身,例如:

$(‘div#div2’).cloest(‘div’).css(‘background’, ‘red’);

这将会将#div2自身变为红色,因为closest()正在查找div,而离#div2最近的div正是其自身。

 

position() && offset()

这两者都是用于读取元素的位置---即由选择器返回的第一个元素的位置。他们都返回包含left和top这两个属性的对象,但是他们返回位置所相对的对象不同。

position()计算相对于偏移父元素---更通俗一点,含有position:relative的元素的最近的父元素或祖先元素---的位置。如果未能找到这样的父元素或祖先元素,那么会计算相对于文档(即视区左上角)的位置。

offset()则总是计算相对于文档的位置,无论元素的父元素或祖先元素的position属性是什么。

offset()和position()的区别概括地说:

  1. 使用position()方法时事实上是把该元素当绝对定位来处理,获取的是该元素相当于最近的一个拥有绝对或者相对定位的父元素的偏移位置。
  2. 使用position()方法时如果其所有的父元素都为默认定位(static)方式,则其处理方式和offset()一样,是当前窗口的相对偏移。
  3. 使用offset()方法不管该元素如何定位,也不管其父元素如何定位,都是获取的该元素相对于当前视口的偏移。

一般情况下,如果要显示的元素B存放在元素A的同一父元素下(即B为A的兄弟节点),这个时候使用position() 是最合适的;

如果显示的元素B存放在DOM的最顶端或者最底端(即其父元素就是body)。这个时候用offset()是最好的。

 

width(),height() && css(‘width’),css(‘height’)

我们首先看看.css("width")与.width()方法的区别。从方法名我们不难看出,此方法获取的是元素的宽度。我们看看下边的例子:

<div id="element" class="width:200;">

<!--element-->

</div>

//结果为:200

alert($("#element").width());

//结果为:200px

alert($("#element").css("width"));

从上边我们可以看出.width()返回的是不带单位的宽度值,而.css("width")返回的是带单位(px)的宽度值。同理,.height()同.css("height")也是一样的。

最后,要说明的一点是当元素宽度为auto时,.css("width")返回的是auto,而.width()返回实际的宽度。

可见,我们应该根据需要有所选择,从而可以少写点代码。避免习惯性的使用css(‘width’),css(‘height’)。

 

下面内容参考:http://blog.csdn.net/youtu_li/article/details/3200688

首先解释下普通元素和非普通元素,非普通元素是指window,document这些 元素对象,普通元素是指除window,document这些非普通元素外的元素,如:div。

对于普通的元素 ,他们的作用相同。比如网页上有一个 div 元素:

 <div style="width:200px;height:200px;"></div>
我们可以使用:

$(function(){
     var width1 = $("div").css("width");
     var width2 = $("div").width();
   })
都可以获取到宽度width。

不过要注意:

.css("width")会带单位, 例子中 会输出 : 200px ;

.width()则不带单位 , 输出 200 ;

对于非普通元素,只能使用 .width()如:

我们想获取 window对象的宽度,我们只能使用$(window).width();输出电脑屏幕的宽度;

使用$(window).css("width");输出 undefined。同理,.css("height")和.height()也一样。

 

click(),bind(),live() && delegate()

内容参考:

http://justcoding.iteye.com/blog/1457883(前半部分同下面链接,注意文章后半部分)

http://www.jquery001.com/click()-bind()-live()-delegate().html

 

click(),bind(),live()都是执行事件时使用的方法,他们之前是有一些区别的,我们在使用这些方法时应该根据需要进行选择。

1.click()方法是我们经常使用的单击事件方法:

$("a").click(function() {
   alert("hello");
});

当点击<a>时,输出hello。

2.click()方法是bind()方法的一种简单方法。在bind()中,jQuery所有JavaScript事件对象,比如focus, mouseover, 和 resize,都是可以作为type参数传递进来的。我们直接看看jQuery文档中的一个例子:

var message = "left";
$("a").bind("click", function() {
   alert(message);
   return false;
});
 
var message = "right";
$("a").bind("contextmenu", function() {
   alert(message);
   return false;
});

上边代码中,无论是左键单击还是右键单击<a>输出总是"right"。为了解决这个问题,我们可以将message作为data参数传递到到bind()方法中,如下:

var message = "left";
$("a").bind("click", { msg: message }, function(e) {
   alert(e.data.msg);
   return false;
});
 
var message = "right";
$("a").bind("contextmenu", { msg: message }, function(e) {
   alert(e.data.msg);
   return false;
});

这样当我们左键单击<a>时,输出"left";当右键单击<a>时,输出"right"。

可见,一般情况下我们使用click()方法就可以了,当需要处理上边这种情况时,我们要使用bind()方法。

3.live()给所有匹配的元素附加一个事件处理函数,即使这个元素是以后再添加进来的也有效。如下:

$("div.live").bind("click", function() {
   alert("success");
});

此时,当点击class为live的div时,输出"success"。此时如果有一个新的元素添加了进来,如下:

$("<div class="live" href="http://www.mamicode.com/#">live</div>").appendTo("body");

这时,当使用上边方法点击class为live的a标签时,不会执行。原因在于,这个元素是在调用bind()之后添加的,而使用live()方法使得在后边添加的元素也能够执行相应的事件,如下:

$("div.live").live("click", function() {
   alert("success");
});

这样,当我们单击class为live的a标签时,如果此a标签是后边添加的,也能照常输出"success"。至于原因,在这里不做具体的说明,本篇主要比较几种方法的区别。

最后,看看delegate()方法,这个方法到目前为止我自己还没有使用过,应该是在1.4.2中才有的。

live()方法的一个不足在于它不支持链式写法:

$("#test").children("a").live("mouseover", function() {
    alert("hello");
});

上边这种写法并不会输出,我们使用delegate()可以写为:

$("#test").delegate("a", "mouseover", function() {
    alert("hello");
});

这样就可以正常的输出我们想要的结果了。本篇总结了click()、bind()、live()和delegate()方法,其中并没有做非常详细的解释,仅望能对大家在具体使用时有所帮助。

 

children() && find()

.children(selector) 方法是返回匹配元素集合中每个元素的所有子元素仅儿子辈)。参数可选,添加参数表示通过选择器进行过滤,对元素进行筛选。

.find(selector)方法是返回匹配元素集合中每个元素的后代。参数是必选的,可以为选择器、jquery对象可元素来对元素进行筛选。

.find() 与 .children() 方法类似,不同的是后者仅沿着 DOM 树向下遍历单一层级。这里的children,理解为儿子,只在儿子这一级遍历。看下例子:

<ul class="level-1">
      <li class="item-i">I</li>
      <li class="item-ii">II
               <ul class="level-2">不包括自己
                       <li class="item-a">A</li>
                       <li class="item-b">B
                                <ul class="level-3">
                                         <li class="item-1">1</li>
                                         <li class="item-2">2</li>
                                         <li class="item-3">3</li>
                                </ul>
                       </li>
                       <li class="item-c">C</li>
               </ul>
      </li>
      <li class="item-iii">III</li>
</ul>
$(‘ul.level-2‘).children().css(‘background-color‘, ‘red‘);

这行代码的结果是,项目 A, B, C 得到红色背景。由于我们没有应用选择器表达式,返回的 jQuery 对象包含了所有子元素。如果应用一个选择器的话,那么只会包括匹配的项目。

<script>
$(document).ready(function(){
    $("#abc").children(".selected").css("color", "blue");
});
</script>
<div id="abc">
      <span>Hello</span>
      <p class="selected">Hello Again</p>
      <div><--换成<p>
               <div class="selected">And Again</div>
               <span class="selected">aaAnd Again</span>
      </div><--换成</p>
      <p>And One Last Time</p>
</div>
(上述代码中,如果按要求将div换成p,运行结果与我想象有所差别,为什么呢(不是只选择孩子节点吗)?现在还不懂,求大牛解释···)

.find()方法要注意的知识点:

1、find是遍历当前元素集合中每个元素的后代。只要符合,不管是儿子辈,孙子辈都可以。

2、与其他的树遍历方法不同,选择器表达式对于 .find() 是必需的参数。如果我们需要实现对所有后代元素的取回,可以传递通配选择器 ‘*‘。

3、find只在后代中遍历,不包括自己。

4、选择器 context 是由 .find() 方法实现的;因此,$(‘li.item-ii‘).find(‘li‘) 等价于 $(‘li‘, ‘li.item-ii‘)。

 

还可以参考链接:

http://www.jb51.net/article/26195.htm

http://www.poluoluo.com/jzxy/201302/197794.html

 

not() && is() && :not()

正如从名称所见,not和is是反义词,但不止这些,两者并不对等。

not()返回选择器不匹配的元素。例如:

$(‘p’).not(‘.someclass’).css(‘color’, ‘red’);

这会将所有不包含someclass类的段落变为红色。

反过来,你想找到包含someclass的段落,你可能会使用:

$(‘p’).is(‘.someclass’).css(‘color’, ‘red’);

事实上,这会导致错误,因为is()不会返回元素,只会返回一个布尔值,她是一个测试函数,看是否有元素匹配选择器。

:not()是not() 的伪选择器等价方法,作用相同只有一点区别,跟其他所有伪选择器相同,你可以在选择器字符串中使用它,而jQuery的字符串解析器会认出它并进行操作,以下示例与前面的not()示例作用相同:

$(‘p:not(.someclass)’). css(‘color’, ‘red’);

 

each() && filter()

这两者用于迭代访问由选择器返回的每个元素并对其进行操作。

each()会循环访问元素,有两种方法。第一种,也是最常用的一种,是将回调函数作为唯一的参数传递,也可以连续对每个元素进行操作,如下:

$(‘p’).each(function(){

      alert($(this).text());

});

他会访问文档中的每一个<p>。

但是each()并不只是作用于选择器的方法,他可以用来处理数组和类似数组的对象,如下:

var myarray = [‘one’, ‘two’];

$.each(myarray, function(key, val){

      alert(‘the value at key ’+key +’is ’+val);

});

filter(),首先,它不同于each(),不能用于数组或对象。

filter()可以访问链中的每一个元素,但如果没有通过某个测试,就会从链中移除该元素。

最常见的用法是,传递给它一个选择器字符串,如下:

$(‘p’).filter(‘.someclass’).css(‘color’, ‘red’);

each()还可以参考:http://www.cnblogs.com/xiaojinhe2/archive/2011/10/12/2208740.html

filter也可以参考W3C中的解释:

如果给定表示 DOM 元素集合的 jQuery 对象,.filter() 方法会用匹配元素的子集构造一个新的 jQuery 对象。所使用的选择器会测试每个元素;所有匹配该选择器的元素都会包含在结果中。

请思考下面这个拥有简单列表的页面:

<ul>
  <li>list item 1</li>
  <li>list item 2</li>
  <li>list item 3</li>
  <li>list item 4</li>
  <li>list item 5</li>
  <li>list item 6</li>
</ul>

我们可以向这个列表项集合应用该方法:

$(‘li‘).filter(‘:even‘).css(‘background-color‘, ‘red‘);

此调用的结果是将项目 1, 3, 5 的背景设置为红色,这是因为它们都匹配选择器(回忆一下,:even 和 :odd 均使用基于 0 的 index)。

使用过滤函数

使用该方法的第二个形式是,通过函数而不是选择器来筛选元素。对于每个元素,如果该函数返回 true,则元素会被包含在已筛选集合中;否则,会排除这个元素。

请看下面这段稍显复杂的 HTML 片段:

<ul>

  <li><strong>list</strong> item 1 - one strong tag</li>

  <li><strong>list</strong> item <strong>2</strong>

   - two <span>strong tags</span></li>

  <li>list item 3</li>

  <li>list item 4</li>

  <li>list item 5</li>

  <li>list item 6</li>

</ul>

我们可以选取这些列表项,然后基于其内容来筛选它们:

$(‘li‘).filter(function(index) {

  return $(‘strong‘, this).length == 1;

}).css(‘background-color‘, ‘red‘);

选择器的语法是:jQuery(selector, [context])(对上段代码中this的解释)

一般情况对jquery的选择器的用法,都是做为第一个参数的用法。其实jquery()函数的这种用法还可以传递第二个参数。传递这个参数的目的是将前面选择器限定在context这个环境中。在默认情况下,即不传第二个参数,选择器从文档根部对 DOM 进行搜索($()将在当前的HTML document中查找DOM元素);如果指定了第二个参数,如一个DOM元素集或jquery对象,那就会在这个context中查找。
 
下面看个例子:

$("div.foo").click(function() {

    $("span", this).addClass("bar");

});

由于我们已经将 span 选择器限定到 this 这个环境中,只有被点击元素中的 span 会得到附加的class。 

 

merge() && extend()

merge()可以将两个数组的内容合并到第一个中,这包含了对第一个数组的永久性改变,他不会生成新的数组,而是将第二个数组内容添加到第一个后面。

extend()参考:http://www.cnblogs.com/RascallySnake/archive/2010/05/07/1729563.html

JQuery的extend扩展方法:

Jquery的扩展方法extend是我们在写插件的过程中常用的方法,该方法有一些重载原型,在此,我们一起去了解了解。

  1.  Jquery的扩展方法原型是:   

 extend(dest,src1,src2,src3...);

它的含义是将src1,src2,src3...合并到dest中,返回值为合并后的dest,由此可以看出该方法合并后,是修改了dest的结构的。如果想要得到合并的结果却又不想修改dest的结构,可以如下使用:

  var newSrc=http://www.mamicode.com/$.extend({},src1,src2,src3...)//也就是将"{}"作为dest参数。

这样就可以将src1,src2,src3...进行合并,然后将合并结果返回给newSrc了。如下例:

var result=$.extend({},{name:"Tom",age:21},{name:"Jerry",sex:"Boy"})

 那么合并后的结果

  result={name:"Jerry",age:21,sex:"Boy"}

也就是说后面的参数如果和前面的参数存在相同的名称,那么后面的会覆盖前面的参数值。

 2.  省略dest参数
      上述的extend方法原型中的dest参数是可以省略的,如果省略了,则该方法就只能有一个src参数,而且是将该src合并到调用extend方法的对象中去,如:

 1).  $.extend(src)
该方法就是将src合并到jquery的全局对象中去,如:

 $.extend({
  hello:function(){alert(‘hello‘);}
  });

就是将hello方法合并到jquery的全局对象中。
2).  $.fn.extend(src)

该方法将src合并到jquery的实例对象中去,如:

 $.fn.extend({
  hello:function(){alert(‘hello‘);}
  });

就是将hello方法合并到jquery的实例对象中。

下面例举几个常用的扩展实例:

$.extend({net:{}});

这是在jquery全局对象中扩展一个net命名空间。

  $.extend($.net,{
   hello:function(){alert(‘hello‘);}
  })

这是将hello方法扩展到之前扩展的Jquery的net命名空间中去。

3.  Jquery的extend方法还有一个重载原型:  

extend(boolean,dest,src1,src2,src3...)

第一个参数boolean代表是否进行深度拷贝,其余参数和前面介绍的一致,什么叫深层拷贝,我们看一个例子:

var result=$.extend( true,  {}, 
    { name: "John", location: {city: "Boston",county:"USA"} }, 
    { last: "Resig", location: {state: "MA",county:"China"} } );

我们可以看出src1中嵌套子对象location:{city:"Boston"},src2中也嵌套子对象location:{state:"MA"},第一个深度拷贝参数为true,那么合并后的结果就是: 

result={name:"John",last:"Resig",
        location:{city:"Boston",state:"MA",county:"China"}}

也就是说它会将src中的嵌套子对象也进行合并,而如果第一个参数boolean为false,我们看看合并的结果是什么,如下:

var result=$.extend( false, {}, 
{ name: "John", location:{city: "Boston",county:"USA"} }, 
{ last: "Resig", location: {state: "MA",county:"China"} } 
                    );

那么合并后的结果就是:

  result={name:"John",last:"Resig",location:{state:"MA",county:"China"}}