JQuery是用于操作页面元素的便捷之道,里面封装了兼容各个浏览器的hack 处理,在幅DOM操作的运用环境中引用jQuery作为辅助工具将会是一个很不错的选择。
一、诞生
在没有jQuery之前要获取DOM元素非常的繁琐:
(1)querySelector
(2)querySelectorAll
(3)getElementById
(4)getElementsByTagName
(5)getElementsByClassName
var btn= document.getElementById("btn");
var text = document.getElementById("text");
btn.onclick = function (e) {
text.style.display = "none";
}
以上操作相比jQuery$(“.name”)的结构而言,是不是非常的方便的。
所以就会想要将以上的选择器如ID选择器等进行封装:
var $ = function (id) {
return document.getElementById(id);
}
$("btn").onclick = function (e) {
$("text").style.display = "none";
}
上面的代码经过改装后可以实现一样的效果,但是上面的隐藏操作还是比较复杂,因而可以进一步进行封装这样需要隐藏元素的时候直接调用hide即可代码量。因为隐藏需要在特定的元素上进行操作,不能像上面直接进行function,利用原型对象进行封装扩展。
function F(id) {
this.ele = document.getElementById(id);
}
F.prototype.hide = function () {
this.ele.style.display = "none";
}
var text = new F("text");
var btn= document.getElementById("btn");
btn.onclick = function () {
text.hide();
}
上面封装的不够完善,获取元素的属性的方法私有没有被共享(继承),所以应该将获取元素的方法写到原型上:
function F(id) {
return this.getElementById(id);
}
F.prototype.getElementById = function (id) {
this.ele = document.getElementById(id);
return this;
}
F.prototype.hide = function () {
this.ele.style.display = "none";
}
var btn = document.getElementById("btn");
btn.onclick = function (e) {
new F("text").hide();
}
有人说我不想调用的时候还来new一下,想要直接利用$的方式进行调用,所以又有如下的改进方式:
var $ = function(id){
return new F(id);
}
function F(id) {
return this.getElementById(id);
}
F.prototype.getElementById = function (id) {
this.ele = document.getElementById(id);
return this;
}
F.prototype.hide = function () {
this.ele.style.display = "none";
}
var btn = document.getElementById("btn");
btn.onclick = function (e) {
$("text").hide();
}
以上的方法中值能够通过id的方式获取到元素,所以应该要继续进行扩展:
var $ = function(selector,context){
return new F(selector,context);
}
function F(selector,context) {
return this.getNodeList(selector,context);
}
F.prototype.getNodeList = function (selector,context) {
context = context || document;
this.element= context.querySelectorAll(selector);
return this;
}
F.prototype.hide = function () {
var len = this.element.length;
for(var i =0; i< len ;i++){
this.nodeList[0].style.display = "none";
}
}
var btn = document.getElementById("btn");
btn.onclick = function (e) {
$("#text").hide();
}
由于querySelectorAll获取的是元素列表所以需要进行遍历操作,当元素如果还有显示的操作时,那就有需要使用一次遍历,对于多个地方重复的代码最好是使用封装,所以再给原型添加一个each的方法:
var $ = function(selector,context){
return new F(selector,context);
}
function F(selector,context) {
return this.getNodeList(selector,context);
}
F.prototype.getNodeList = function (selector,context) {
context = context || document;
this.element= context.querySelectorAll(selector);
return this;
}
F.prototype.each = function (fn) {
var len = this.element.length;
for(var i =0;i<len ;i++){
fn.call(this.nodeList[i]);
}
}
F.prototype.hide = function () {
this.each(function () {
this.style.display = "none";
})
}
var btn = document.getElementById("btn");
btn.onclick = function (e) {
$("#text").hide();
}
上面的初始化时还是和jQuery有些不一样,其中多了element的属性,同时不能直接利用$()[0]这样下标的方式进行访问元素成员,而是需要以$().element[0]的形式进行访问,所以还需要进行改进,使得this直接成为类数组对象:
var $ = function(selector,context){
return new F(selector,context);
}
function F(selector,context) {
return this.init(selector,context);
}
F.prototype.init = function (selector,context) {
context = context || document;
var nodeList = context.querySelectorAll(selector);
this.length = nodeList.length;
for (var i=0; i<nodeList.length; i+=1) {
this[i] = nodeList[i];
}
return this;
}
F.prototype.each = function (fn) {
var len = this.length;
for(var i =0;i<len ;i++){
fn.call(this[i]);
}
}
F.prototype.hide = function () {
this.each(function () {
this.style.display = "none";
})
}
var btn = document.getElementById("btn");
btn.onclick = function (e) {
$("#text").hide();
}
还没结束哦!!!!继续将F进行替换:
var $ = function(selector,context){
return new $.fn(selector,context);
}
$.fn =function (selector,context) {
return this.init(selector,context);
}
$.fn.prototype.init = function (selector,context) {
context = context || document;
var nodeList = context.querySelectorAll(selector);
this.length = nodeList.length;
for (var i=0; i<nodeList.length; i+=1) {
this[i] = nodeList[i];
}
return this;
}
$.fn.prototype.each = function (fn) {
var len = this.length;
for(var i =0;i<len ;i++){
fn.call(this[i]);
}
}
$.fn.prototype.hide = function () {
this.each(function () {
this.style.display = "none";
})
}
var btn = document.getElementById("btn");
btn.onclick = function (e) {
$("#text").hide();
}
同时上面的代码每次都会看到prototype的身影,能不能继续改进能:
var $ = function(selector,context){
return new F(selector,context);
}
F =function (selector,context) {
return this.init(selector,context);
}
$.fn = F.prototype;
$.fn.init = function (selector,context) {
context = context || document;
var nodeList = context.querySelectorAll(selector);
this.length = nodeList.length;
for (var i=0; i<nodeList.length; i+=1) {
this[i] = nodeList[i];
}
return this;
}
$.fn.each = function (fn) {
var len = this.length;
for(var i =0;i<len ;i++){
fn.call(this[i]);
}
}
$.fn.hide = function () {
this.each(function () {
this.style.display = "none";
})
}
var btn = document.getElementById("btn");
btn.onclick = function (e) {
$("#text").hide();
}
不过还是和jQuery有些不一样,多了一个多余的F,而 本身就是一个function,所以可以将$.fn=F.prototype处改为$.fn=$.prototype,这样相当于所有的属性、方法均是挂在 对象上的,初始化的希望将$将对象进行实例化这样外面就不需要在new了,如果直接:
var $ = function(selector,context){
return new $(selector,context);
}
$.fn = $.prototype;
$.fn.init = function (selector,context) {
context = context || document;
var nodeList = context.querySelectorAll(selector);
this.length = nodeList.length;
for (var i=0; i<nodeList.length; i+=1) {
this[i] = nodeList[i];
}
return this;
}
利用上诉方式将会导致循环引用出错,所以在jQuery中利用了他的属性init方法作为构造函数,结合原型链达到效果:
var $ = function(selector,context){
return new $.fn.init(selector,context);
}
$.fn = $.prototype;
$.fn.init.prototype = $.fn;//这一步非常关键,如果没有这一步上面new之后返回的是init的实例,将会是一个空的实例,利用此处使得返回的对象将会继承$的所有属性,以及下面的each等方法。
$.fn.init = function (selector,context) {
context = context || document;
var nodeList = context.querySelectorAll(selector);
this.length = nodeList.length;
for (var i=0; i<nodeList.length; i+=1) {
this[i] = nodeList[i];
}
return this;
}
$.fn.each = function (fn) {
var len = this.length;
for(var i =0;i<len ;i++){
fn.call(this[i]);
}
}
$.fn.hide = function () {
this.each(function () {
this.style.display = "none";
})
}
var btn = document.getElementById("btn");
btn.onclick = function (e) {
$("#text").hide();
}
上面就是jQuery的基本思想和原理,纯属本人理解,如有不对之处请指出,以便相互学习!!!!
参考链接:http://www.cnblogs.com/kidney/p/5879255.html