【学习笔记】jQuery的实现原理
来源:互联网 发布:ssh建立连接的端口号 编辑:程序博客网 时间:2024/06/05 20:57
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,而
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
- 【学习笔记】jQuery的实现原理
- jQuery的实现原理
- jQuery实现的原理简介
- jquery的delegate实现原理
- jquery选择器的实现原理
- jQuery对象实现的原理
- JQuery的学习笔记
- jQuery的学习笔记
- jquery的学习笔记
- RING3代码HOOK的原理实现 (学习笔记1)
- android学习笔记---手机拍照功能的实现,及原理
- Hbase 学习笔记: Hbase的架构和实现原理
- 个人学习笔记---linux原子操作的实现原理
- C++学习笔记:多态的实现原理
- 编译原理学习笔记(二)翻译程序的实现
- 【学习笔记】Vue中实现双向数据绑定的原理
- JQuery学习笔记之实现菜单的下拉
- jQuery 学习笔记 (jQuery DOM的操作)
- html表单基础
- spring声明式事务源码剖析(中)
- 解决IE浏览器下document click事件失效问题
- Java NIO系列教程(6):Selector
- 剑指offer(23)—二叉搜索树的后序遍历序列
- 【学习笔记】jQuery的实现原理
- Unity 使用 Runtime NavMesh(运行时导航),实现AI在场景变化时,重新计算路线
- POJ1273-Drainage Ditches
- 一个想法照进现实-《IT连》创业项目:聊聊最近两三事
- 对于ORACLE RAC集群修改MAX_STRING_SIZE的方法(varchar2字段扩展到32K)
- cocos-js,Widget的addTouchEventListener改善
- 10个有关RESTful API良好设计的最佳实践
- 升级Glibc2.14的坑爹记录
- cmd下javac 错误: 编码GBK的不可映射字符