首页风格
门户
博客

jQuery到javascript的参考 - 帮助你了解javascript底层

日期:2012/01/25  来源:GBin1.com

jQuery到javascript的参考 - 帮助你了解javascript底层

越来越多的开发人员都先接触jQuery而非javascript。很多情况下,对于新手都很幸运。      他们使用很多新的javascript类库,帮助他们快速简单的处理DOM,但是很不幸,他们都不是真正了解这些API。

在本文中,我们将介绍一些常用的jQuery应用,并且将他们转化成现代和遗留的javascript。

开始之前

注意我们使用的一些遗留代码例子将使用简单的跨浏览器的addEvent方法。这个方法保证所有的W3C推荐的事件模型,addEventListener和IE的遗留attachEvent都正常执行。

所以,当我们参考addEvent(els,event,handler)时,参考下面方法:

var addEvent = (function () {
   var filter = function(el, type, fn) {
      for ( var i = 0, len = el.length; i < len; i++ ) {
         addEvent(el[i], type, fn);
      }
   };
   if ( document.addEventListener ) {
      return function (el, type, fn) {
         if ( el && el.nodeName || el === window ) {
            el.addEventListener(type, fn, false);
         } else if (el && el.length) {
            filter(el, type, fn);
         }
      };
   }
 
   return function (el, type, fn) {
      if ( el && el.nodeName || el === window ) {
         el.attachEvent('on' + type, function () { return fn.call(el, window.event); });
      } else if ( el && el.length ) {
         filter(el, type, fn);
      }
   };
})();
 
// usage
addEvent( document.getElementsByTagName('a'), 'click', fn);

1. $('#container');

这个方法调用将会查询DOM中一个id为container的元素,并且创建一个新的jQuery对象。

现代浏览器JS

var container = document.querySelector('#container');

querySelectors是选择器API的一个部分,提供我们通过CSS查询DOM的能力

这个特定方法返回第一个匹配传递选择器的元素

传统遗留代码

var container = document.getElementById('container');

注意你是如何参考元素的。当使用getElementById,你将单独传递一个值,然而使用querySelector,则需要一个CSS选择器

2. $('#container').find('li');

这次我们不单单找一个元素,我们需要查找所有#container的子元素。

现代浏览器

var list = document.querySelectorAll('#container li'); 

querySelectorAPI返回所有的符合指定CSS选择器的元素

selector限制 :虽然所有的相关的浏览器都支持Selector API,你传递的指定CSS选择器还是受限于浏览器,IE8只支持CSS2.1选择器。

传统遗留代码

var list = document.getElementById('container').getElementsByTagName('li');

3 – $('a').on('click', fn); 

在这里例子中,我们将添加一个click事件到所有的anchor标签

现代浏览器

[].forEach.call( document.querySelectorAll('a'), function(el) {
   // anchor was clicked
});

以上代码看起来比较恐怖,但是不是很差。因为querySelectorAll返回了一个静态的NodeList而不是一个数组,我们无法直接访问访问,如,foreach。但这个可以被通过调用forEach来弥补,通过作为this来传递querySelectorAll的结果。

传统遗留代码

var anchors = document.getElementsbyTagName('a');
addEvent(anchors, 'click', fn);

4 – $('ul').on('click', 'a', fn);

这个例子稍有不同。这一次,我们使用event delegation。click监听将会被应用到无序的列表中。然而,callback功能将只会在目标为anchor标签时才调用。

现代浏览器

document.addEventListener('click', function(e) {
   if ( e.target.matchesSelector('ul a') ) {
      // proceed
   }
}, false);

技术上来讲,这个JS方法和上面jQUery的不同,它将事件监听直接添加到了document。使用新的matchesSelector方法来判断是否目标结点被点击。这个方法我们添加了一个单一的事件监听,而不是很多

请注意,当我们撰写这个文章的时候,所有的浏览器通过他们自己的各自的后缀来执行了matchesSelector:mozMatchesSelector,webkitMatchesSelector。为了统一代码,我们执行如下:

var matches;
 
(function(doc) {
   matches =
      doc.matchesSelector ||
      doc.webkitMatchesSelector ||
      doc.mozMatchesSelector ||
      doc.oMatchesSelector ||
      doc.msMatchesSelector;
})(document.documentElement);
 
document.addEventListener('click', function(e) {
   if ( matches.call( e.target, 'ul a') ) {
      // proceed
   }
}, false);

使用以上代码,在webkit内核浏览器中,会参考 webkitMatchesSelector,而在mozilla,则使用mozMatchesSelector

传统遗留代码

var uls = document.getElementsByTagName('ul');
 
addEvent(uls, 'click', function() {
   var target = e.target || e.srcElement;
   if ( target && target.nodeName === 'A' ) {
      // proceed
   }
});

我们判断是否nodeName属性等于我们需要的查询。特别注意老版本的IE浏览器有时候使用自己的规则。你不能够直接从event访问target,你需要查看event.srcElement。

5 - $('#box').addClass('wrap');

jQuery提供以上API来修改class名字

现代浏览器

document.querySelector('#box').classList.add('wrap');

新的技巧使用新的classList API来添加,删除和变化class名字

var container = document.querySelector('#box');
 
container.classList.add('wrap');
container.classList.remove('wrap');
container.classList.toggle('wrap');

传统遗留代码

var box = document.getElementById('box'),
 
    hasClass = function (el, cl) {
        var regex = new RegExp('(?:\\s|^)' + cl + '(?:\\s|$)');
        return !!el.className.match(regex);
    },
 
    addClass = function (el, cl) {
        el.className += ' ' + cl;
    },
 
    removeClass = function (el, cl) {
        var regex = new RegExp('(?:\\s|^)' + cl + '(?:\\s|$)');
        el.className = el.className.replace(regex, ' ');
    },
 
    toggleClass = function (el, cl) {
        hasClass(el, cl) ? removeClass(el, cl) : addClass(el, cl);
 
    };
 
addClass(box, 'drago');
removeClass(box, 'drago');
toggleClass(box, 'drago'); // if the element does not have a class of 'drago', add one.

6 - $('#list').next();

jQuery的next方法返回了当前元素后的元素

现代浏览器

var next = document.querySelector('#list').nextElementSibling; // IE9

nextElementSibling将会参考next元素节点,而不是任何节点(text,comment,element)。很不幸IE8及其以下。

传统遗留代码

var list = document.getElementById('list'),
   next = list.nextSibling;
 
// we want the next element node...not text.
while ( next.nodeType > 1 ) next = next.nextSibling;

这里有几种方法来实现。这个例子中,我们检测跟随的指定nodeType。可以是文本, 元素或者一个注释。我们如果需要文本,我们则需要nodeType为1。如果next 。nodeType大于1,我们就忽略并且继,直到是一个文字节点。

7 - $('<div id=box></div>').appendTo('body');

除了查询,jQuery允许注入和创建元素。

传统遗留代码

var div = document.createElement('div');
div.id = 'box';
document.body.appendChild(div);

这里没有什么现代方法来完成这个任务。这就是我们使用了很长时间的方法来实现。你需要添加内容到元素。你可以使用innerHTML或者createTextNode.

div.appendChild( document.createTextNode('wacka wacka') );

// or

div.innerHTML = 'wacka wacka';

8 – $(document).ready(fn)

jQuery的document.ready方法非常的方便。允许我们在DOM加载后开始执行节点

现代浏览器

document.addEventListener('DOMContentLoaded', function() {
// have fun
});

标准的HTML5,一但完成document加载DOMContentLoaded事件将会被触发

传统遗留代码

// http://dustindiaz.com/smallest-domready-ever
function ready(cb) {
/in/.test(document.readyState) // in = loadINg
? setTimeout('ready('+cb+')', 9)
: cb();
}

ready(function() {
// grab something from the DOM
});

以上代码,每隔9毫秒,将检测document.readyState状态。如果"loading"返回,document然而没有被完整解析(/in/。test(), 一旦解析完成,document.readyState将会等于“完成”,这个时候用户callback被执行

9 – $('.box').css('color', 'red');

如果可能的话,尽量使用class来提供样式。然而,有的时候,样式需要动态,所以需要作为一个属性插入。

现代浏览器

[].forEach.call( document.querySelectorAll('.box'), function(el) {
el.style.color = 'red'; // or add a class
});

这里我们同样使用[].forEach.call()技巧来过滤所有的class为box的类,通过样式对象来使得他们变红。

传统遗留代码

var box = document.getElementsByClassName('box'), // refer to example #10 below for a cross-browser solution
i = box.length;

while ( i-- > 0 && (box[i].style.color = 'red') );

这一次,我们使用while循环,如下:

var i = 0, len;

for ( len = box.length; i < len; i++ ) {
box[i].style.color = 'red';
}

10 – $()

很清楚,我们目的不是拷贝整个jQuery API。典型的,对于非jQuery对象,$或者$$用来作为DOM返回一个或者多个元素的快捷方式

现代浏览器

var $ = function(el) {
return document.querySelectorAll(el);
};
// Usage = $('.box');

传统遗留代码

if ( !document.getElementsByClassName ) {
document.getElementsByClassName = function(cl, tag) {
var els, matches = [],
i = 0, len,
regex = new RegExp('(?:\\s|^)' + cl + '(?:\\s|$)');

// If no tag name is specified,
// we have to grab EVERY element from the DOM
els = document.getElementsByTagName(tag || "*");
if ( !els[0] ) return false;

for ( len = els.length; i < len; i++ ) {
if ( els[i].className.match(regex) ) {
matches.push( els[i]);
}
}
return matches; // an array of elements that have the desired classname
};
}

// Very simple implementation. We're only checking for an id, class, or tag name.
// Does not accept CSS selectors in pre-querySelector browsers.
var $ = function(el, tag) {
var firstChar = el.charAt(0);

if ( document.querySelectorAll ) return document.querySelectorAll(el);

switch ( firstChar ) {
case "#":
return document.getElementById( el.slice(1) );
case ".":
return document.getElementsByClassName( el.slice(1), tag );
default:
return document.getElementsByTagName(el);
}
};

// Usage
$('#container');
$('.box'); // any element with a class of box
$('.box', 'div'); // look for divs with a class of box
$('p'); // get all p elements

使用传统的方法不是很简单,这种情况你需要使用jQuery类似的类库。jQuery针对DOM优化,这就是为什么jQuery如此流行!以上代码并不支持复杂的CSS选择器。

总结

对于我们来说非常重要是我并没有鼓励你放弃jQuery。我几乎在每一个我的项目中都使用jQuery。希望大家喜欢!

来源: jQuery到javascript的参考 - 帮助你了解javascript底层

喜欢我们的文章请您与朋友分享:

?ü?à

留言


  1. Jax

    这个文章超好,适合我这种不懂javascript做jquery开发的人!
    2012-4-7 下午8:09
(请输入阿拉伯数字)
今日推荐