jQuery插件编写及链式编程模型
jQuery插件编写及链式编程模型小结
JQuery极大的提高了我们编写JavaScript的效率,让我们可以愉快的编写代码,做出各种特效。大多数情况下,我们都是使用别人开发的JQuery插件,今天我们就来看看如何把我们常用的功能做出JQuery插件,然后像使用jQuery那样来操作DOM.
1、jQuery插件模板
关于jQuery插件的编写,我们可以通过为jQuery.fn增加一个新的函数来编写jQuery插件。属性的名字就是你的插件的名字,其模板如下:
(function($){
$.fn.myJQPlugin = function(){
//TODO:add your code
}
})(jQuery);
其中myJQPlugin 就是你插件的名字,Function里面的代码就是你插件的功能实现代码。
2、与DOM交互
给插件起好名字后,下面就可以编写我们的代码了,但是编写之前,必须要说一说上下文。在插件内部的范围中,this关键字指向的是jQuery对象。人们很容易误解这一点,因为在正常使用jQuery的时候,this通常指向的是一个DOM元素。不了解这一点,会经常使用$又包装了一次。
(function( $ ){
$.fn.myJQPlugin = function() {
// 没有必要使用$(this)
// $(this) 跟 $($('#element'))是一样的
this.html("Hello,world");
this.click(function(){
this.hide(); //注意这里的this不再指向jQuery元素,这里的this指向当前这个function对象
});
};
})( jQuery );
这里又要提到this的指向问题,比如我们想实现一个功能,点击DOM元素,隐藏当前元素,虽然说this指向的是jQuery对象,但是在click中,this的指向发生了变化,指向了它所在的function.所以我们在click方法里面访问当前元素,就要通过变量了,实现方法如下:
(function( $ ){
$.fn.myJQPlugin = function() {
// 没有必要使用$(this)
// $(this) 跟 $($('#element'))是一样的
this.html("Hello,world");
var $this = $(this);
this.click(function(){
$this.hide(); //注意这里的this不再指向jQuery元素,这里的this指向当前这个function对象
});
};
})( jQuery );
我们声明$this变量来保存this对象,这样我们需要使用当前元素时,直接使用$this就可以了。下面我们通过一个完整的实例来测试一下:
其中html页面的代码如下:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="jquery.js" type="text/javascript"></script>
<script src="1.js" type="text/javascript"></script>
</head>
<body>
<div id="container" style="width:800px;height:200px; border:2px #000 solid;padding:20px;font-size:20px;">Hello,world</div>
</body>
<script type="text/javascript">
$('#container').myJQPlugin();
</script>
</html>
jQuery插件的js代码如下:
(function($){
$.fn.myJQPlugin = function(){
this.css("color","red"); //字体颜色为红色
this.hide();
this.slideDown(200); //先隐藏,然后通过slideDown显示出来
var $this = $(this);
this.click(function(){
$this.html("Thanks,good bye!"); //显示信息,然后淡出
$this.fadeOut(2000);
});
}
})(jQuery);
这个插件的功能就是首先让元素下拉显示,然后点击元素时显示再见信息,然后经过2s后淡出。这里大家可以试试在click事件里面使用this会怎么样。
1、为什么要用链式操作?
实际上链式操作仅仅是通过对象上的方法最后加上return this. 把对象再返回回来,对象当然可以继续调用方法啦,所以就可以链式操作了。那么,简单实现一个:
//定义一个JS类
function Demo() { }
//扩展它的prototype
Demo.prototype ={
setName:function (name) {
this.name = name;
return this;
},
getName:function () {
return this.name;
},
setAge:function (age) {
this.age = age;
return this;
}
}; ////工厂函数
function D() {
return new Demo();
}
//去实现可链式的调用
D().setName("CJ").setAge(18).setName();
一般的解释:
节省代码量,代码看起来更优雅。例如如果没有链式,那么你可能需要这样写代码:
document.getElementById("ele").dosomething();
document.getElementById("ele").dootherthing();
这个代码中调用了两次document.getElementById来获取DOM树的元素,这样消耗比较大,而且要写两行,而链式只要写一行,节省了代码……
但我们也可以用缓存元素啊。比如:
var ele = document.getElementById("ele");
ele.dosomething();
ele.dootherthing();
而且两行并没有比一行多多少代码,甚至相应的封装反而使得代码更多了。
最糟糕的是所有对象的方法返回的都是对象本身,也就是说没有返回值,这不一定在任何环境下都适合。
2、那么到底为什么要用链式操作呢?
为了更好的异步体验Javascript是无阻塞语言,所以他不是没阻塞,而是不能阻塞,所以他需要通过事件来驱动,异步来完成一些本需要阻塞进程的操作。
但是异步编程是一种令人疯狂的东西……运行时候是分离的倒不要紧,但是编写代码时候也是分离的就……
常见的异步编程模型有哪些呢?
(1)回调函数 :
所谓的回调函数,意指先在系统的某个地方对函数进行注册,让系统知道这个函数的存在,然后在以后,当某个事件发生时,再调用这个函数对事件进行响应。
function fun(num, callback){
if(num < 0) {
alert("分数不能为负,输入错误!");
}else if(num == 0){
alert("该学生可能未参加考试!");
}else {
alert("调用高层函数处理!");
setTimeout(function(){callback();}, 1000);
}
}
这里callback则是回调函数。可以发现只有当num为非负数时候callback才会调用。
但是问题,如果我们不看函数内部,我们并不知道callback会几时调用,在什么情况下调用,代码间产生了一定耦合,流程上也会产生一定的混乱。
虽然回调函数是一种简单而易于部署的实现异步的方法,但从编程体验来说它却不够好。
(2)链式异步 :
个人觉得链式操作最值得称赞的还是其解决了异步编程模型的执行流程不清晰的问题。jQuery中$(document).ready就非常好的阐释了这一理念。DOMContentLoaded是一个事件,在DOM并未加载前,jQuery的大部分操作都不会奏效,但jQuery的设计者并没有把他当成事件一样来处理,而是转成一种“选其对象,对其操作”的思路。$选择了document对象,ready是其方法进行操作。这样子流程问题就非常清晰了,在链条越后位置的方法就越后执行。
(function(){
var isReady=false; //判断onDOMReady方法是否已经被执行过
var readyList= [];//把需要执行的方法先暂存在这个数组里
var timer;//定时器句柄
ready=function(fn) {
if (isReady )
fn.call( document);
else
readyList.push( function() { return fn.call(this);});
return this;
}
var onDOMReady=function(){
for(var i=0;i<readyList.length;i++){
readyList[i].apply(document);
}
readyList = null;
}
var bindReady = function(evt){
if(isReady) return;
isReady=true;
onDOMReady.call(window);
if(document.removeEventListener){
document.removeEventListener("DOMContentLoaded", bindReady, false);
} else if(document.attachEvent){
document.detachEvent("onreadystatechange", bindReady);
if(window == window.top){
clearInterval(timer);
timer = null;
}
}
};
if(document.addEventListener){
document.addEventListener("DOMContentLoaded", bindReady, false);
}else if(document.attachEvent){
document.attachEvent("onreadystatechange", function(){
if((/loaded|complete/).test(document.readyState))
bindReady();
});
if(window == window.top){
timer = setInterval(function(){
try{
isReady||document.documentElement.doScroll('left');//在IE下用能否执行doScroll判断dom是否加载完毕
}
catch(e){
return;
}
bindReady();
},5);
}
}
})();
上面的代码不能用$(document).ready,而应该是window.ready。
(3)Promise :
CommonJS中的异步编程模型也延续了这一想法,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。
所以我们可以这样写:
f1().then(f2).then(f3);
这种方法我们无需太过关注实现,也不太需要理解异步,只要懂得通过函数选对象,通过then进行操作,就能进行异步编程。
在jQuery中,一个插件紧紧是修改收集到的元素,然后返回这个元素让链条上的下一个使用。这是jQuery设计的精美之处,也是jQuery如此流行的原因之一。为了保证可链式,你必须返回this。如下代码:
(function( $ ){
$.fn.resize = function( type, value ) {
return this.each(function() {
var $this = $(this);
if (!type || type == 'width' ) {
$this.width(value);
}
if ( !type || type == 'height' ) {
$this.height(value);
}
});
};
})(jQuery);
调用方法如下:
$('div').resize('width', '600').css('color','blue');
编写jQuery插件可以充分利用库,将公用的函数抽象出来,“循环利用”。以下是简短的总结:
- 使用(function($){//plugin})(jQuery);来包装你的插件
- 不要在插件的初始范围中重复包裹
- 除非你返回原始值,否则返回this指针来保证可链式
- 不要用一串参数,而是使用一个对象,并且设置默认值
- 一个插件,不要为jQuery.fn附上多个函数
- 为你的函数,事件,数据附着到某个命名空间
jQuery插件开发 http://www.cnblogs.com/playerlife/archive/2012/05/11/2495269.html
jQuery链式操作如何实现以及为什么要用链式操作 http://www.jb51.net/article/33342.htm
jQuery插件编写及链式编程模型的更多相关文章
- jQuery插件编写及链式编程模型小结
JQuery极大的提高了我们编写JavaScript的效率,让我们可以愉快的编写代码,做出各种特效.大多数情况下,我们都是使用别人开发的JQuery插件,今天我们就来看看如何把我们常用的功能做出JQu ...
- ASP.NET MVC学前篇之扩展方法、链式编程
ASP.NET MVC学前篇之扩展方法.链式编程 前言 目的没有别的,就是介绍几点在ASP.NETMVC 用到C#语言特性,还有一些其他琐碎的知识点,强行的划分一个范围的话,只能说都跟MVC有关,有的 ...
- jQuery编程基础精华01(jQuery简介,顶级对象$,jQuery对象、Dom对象,链式编程,选择器)
jQuery简介 什么是jQuery? jQuery就是一个JavaScript函数库,没什么特别的.(开源)联想SQLHelper类 jQuery能做什么?jQuery是做什么的? jQuery本身 ...
- 原生JS实现jquery的链式编程。
这是我根据之前遇到的一个面试题,题目:用原生JS实现$("#ct").on("click",fn).attr("id"). 然后看了篇jqu ...
- 模拟jquery底层链式编程
//特点1:快级作用域,程序启动自动执行 //内部的成员变量,外部无法访问(除了var) //简单的函数链式调用 function Dog(){ this.run=function(){ alert( ...
- 从零开始学 Web 之 jQuery(三)元素操作,链式编程,动画方法
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- 从零开始学 Web 之 jQuery(七)事件冒泡,事件参数对象,链式编程原理
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- jQuery 筛选器 链式编程操作
$('#i1').next() 下一个标签$('#i1').nextAll() 兄弟标签中,所有下一个标签$('#i1').nextUntil('#ii1') 兄弟标签中,从下一个标签到id为ii1的 ...
- Jquery链式编程及Index()详解
Jquery中的方法基本 上都可以返回一个Jquery对象, 如: <body> <div class="divcontent"> <p>中国& ...
随机推荐
- jQuery -> bind / live / delegate 终结者 - on
最近的一项研究jQuery.利用获得的最新版本1.11.1. 据该书打下面的代码示例,,反正也发现跑不起来. html <div class="container"> ...
- fcitx
安装完成后首先面对的问题是全英文无法显示汉字和输入汉字的问题.需要找到光盘上的2个中文支持字体包安装上即可.文件名如下,注意不同版本文件明后面数字部分可能会不同,其代表版本号.下面是Red Hat E ...
- 全栈JavaScript之路(十七)HTML5 新增字符集属性
HTML5 添加�了几个文档字符集属性. document.charset : 表示文档的实际使用的字符集. document.defaultCharset: 表示默认的字符集,跟浏览器以及操作系统设 ...
- 读书时间《JavaScript高级程序设计》一:基础篇
第一次看了<JavaScript高级程序设计>第二版,那时见到手上的书,第一感觉真是好厚的一本书啊.现在再次回顾一下,看的是<JavaScript高级程序设计>第三版,并记录一 ...
- Python学习笔记12:标准库之对象序列化(pickle包,cPickle包)
计算机的内存中存储的是二进制的序列. 我们能够直接将某个对象所相应位置的数据抓取下来,转换成文本流 (这个过程叫做serialize),然后将文本流存入到文件里. 因为Python在创建对象时,要參考 ...
- aauto攫http数据
说明:灵巧使用上述数据的抓取网页简单的例子. 样例:想把某站点的数据抓回来.然后保存在数据库里边. 步骤:1.打开sql.new一个数据库Test.新建一个表test. 2.打开快手.准备抓数据,以这 ...
- etl工具,kettle实现了周期
Kettle这是国外的来源ETL工具,纯java写.能Window.Linux.Unix在执行.绿色无需安装,稳定高效的数据提取. 业务模型: 在关系型数据库中有张非常大的数据存储表,被设计成奇偶库存 ...
- winform正在使用dsoframer迅速"Unable to display the inactive document.Click here to reacitive the document."
于winform正在使用dsoframer 1.3加载word档,但在axFramerControl1.Open("NPOI.docx");于axFramerControl1控制显 ...
- ios 类似的效果淘宝商品详细页面
今天试着写ios 分类似影响淘宝的商品详细页面 我使用第三方库EGORefreshTableHeaderView有一个下拉效果刷新PWLoadMoreTableFooterView上拉电阻负载许多其他 ...
- HTML DOM nodeName nodeValue
在javascript在,我们得title在标签和文本,它们通常要求这样做 var obj =document.getElementsById("id1"); obj.nodeNa ...