用jquery写代码的时候总是很方便,少写很多代码。那么为什么会这样呢?我觉得主要有三个原因:
① jquery封装了获取dom的方法,只需要一个$就可以方便地获取你想要得dmo节点
② 链式调用,比如你可以这样写代码:
$("#a").show().height(20);
而不需要这样写
$("#a").show();
$("#a").height(20);
③ 对象的批量操作。假如你需要对下面的列表进行同样的操作
<li class="list">列表</li> <li class="list">列表</li> <li class="list">列表</li> <li class="list">列表</li> <li class="list">列表</li> <li class="list">列表</li> <li class="list">列表</li> <li class="list">列表</li> <li class="list">列表</li> <li class="list">列表</li>
那么你需要这样写:
var list = document.getElementsByClassName("list"); for (var i = 0, len = list.length; i < len; i++) { list[i].innerHTML = "修改"; }
很麻烦是吧,要使用for循环。但是如果你用jquery写,只需要这样:
$(".list").html("修改");
那么这样方便的代码编写方式,它的背后是如何运作的。
首先是实现$方法,按照直线思维,你一定以为$方法是这样的:
function $(selector){ if(selector带#号){ return document.getElementById(selector); }else if(selector带.号){ return document.getElementsByClassName(selector); }else{ ................. } }
其实不是,如果是这样,那就太简单了,充其量只是对 document.getElement 的封装。你既不能实现链式调用也不能实现批量操作
先上完整代码,再做分析:
1 function _$(els) { 2 3 this.elements = []; 4 element = document.getElementsByClassName(els); 5 for (var i = 0, len = element.length; i < len; i++) { 6 this.elements.push(element[i]); 7 } 8 9 } 10 _$.prototype = { 11 each: function(fn) { 12 for ( var i = 0, len = this.elements.length; i < len; ++i ) { 13 fn.call(this, this.elements[i]); 14 } 15 return this; 16 }, 17 html: function(text) { 18 var that = this; 19 this.each(function(el) { 20 el.innerHTML = text; 21 }); 22 return this; 23 } 24 25 }; 26 window.$ = function(selector) { 27 return new _$(selector); 28 }; 29 30 31 $("list").html("修改").hide();
为了方便理解,这里的_$方法只实现使用class来获取dom结点。如果要实现完整的,类似jquery的获取dom结点的方法,还需要写一些正则和字符串操作。
这里_$通过 document.getElementsByClassName 来获取到dom节点后通过push将这些dom结点放到了数组 elements中。
而且最关键的是,我在_$的prototype上定义了两个方法。
第一个方法 each ,这个方法的作用就是实现批量操作。
它会循环获取我们在_$的时候放置的数组 elements中的每一个元素,并使用 call将参数fn的上下文设置为this,再将每个elements中的dom结点传递给fn。这就产生了批量操作的效果。
看到第二个方法 html,这个方法是改变dom的内容。可以看到在html中使用了each方法来批量操作。最后还 return this; 这句使得原形上的方法可以链式调用。
所以,现在我们可以不依赖jquery而可以这样写代码:
$("list").html("修改")
在这个基础上你还可以实现很多方法,例如可以在实现一个hide()方法来隐藏结点:
1 function _$(els) { 2 3 this.elements = []; 4 element = document.getElementsByClassName(els); 5 for (var i = 0, len = element.length; i < len; i++) { 6 this.elements.push(element[i]); 7 } 8 9 } 10 _$.prototype = { 11 each: function(fn) { 12 for ( var i = 0, len = this.elements.length; i < len; ++i ) { 13 fn.call(this, this.elements[i]); 14 } 15 return this; 16 }, 17 html: function(text) { 18 var that = this; 19 this.each(function(el) { 20 el.innerHTML = text; 21 }); 22 return this; 23 }, 24 hide: function() { 25 var that = this; 26 this.each(function(el) { 27 el.style["display"] = "none"; 28 }); 29 return this; 30 } 31 32 }; 33 window.$ = function(selector) { 34 return new _$(selector); 35 }; 36 37 38 $("list").html("修改").hide();
可以看出来,这篇文章没有将很多代码细节,意在让你理解一个可以批量操作,链式调用的框架的大概架构是如何的。
补充:jquery使用方便还有一个很重要的原因,它兼容各个浏览器。