jQuery的链式操作

时间:2022-07-23
本文章向大家介绍jQuery的链式操作,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

什么是链式操作呢?我们来看看,本来应该写

成这样子的:

$(".stripe tr").mouseover(function(){

    $(this).addClass("over");
})

$(".stripe tr").mouseout(function(){

    $(this).removeClass("over"); 
})

但是我们写成了:

$(".stripe tr").mouseover(function(){$(this).addClass("over");}).mouseout(function(){$(this).removeClass("over");})

在jQuery中,执行完mouseover或者mouseout等方法之后,都会返回当前的对象,所以可以进行链式操作(注意语法)

什么要用链式操作呢?

为了更好的异步体验

Javascript是无阻塞语言,所以他不是没阻塞,而是不能阻塞,所以他需要通过事件来驱动,异步来完成一些本需要阻塞进程的操作。

但是异步编程是一种令人疯狂的东西……运行时候是分离的倒不要紧,但是编写代码时候也是分离的就……

常见的异步编程模型有哪些呢?

•回调函数

所谓的回调函数,意指先在系统的某个地方对函数进行注册,让系统知道这个函数的存在,然后在以后,当某个事件发生时,再调用这个函数对事件进行响应。

. 代码如下:

function f(num, callback){

    if(num<0) {

        alert("调用低层函数处理!");

        alert("分数不能为负,输入错误!");

    }else if(num==0){

        alert("调用低层函数处理!");

        alert("该学生可能未参加考试!");

    }else{

        alert("调用高层函数处理!");

        setTimeout(function(){callback();}, 1000);

    }

}

这里callback则是回调函数。可以发现只有当num为非负数时候callback才会调用。

但是问题,如果我们不看函数内部,我们并不知道callback会几时调用,在什么情况下调用,代码间产生了一定耦合,流程上也会产生一定的混乱。

虽然回调函数是一种简单而易于部署的实现异步的方法,但从编程体验来说它却不够好。

•事件监听

也就是采用事件驱动,执行顺序取决于事件顺序。

. 代码如下:

function EventTarget(){

    this.handlers = {};

}

EventTarget.prototype = {

    constructor: EventTarget,

    addHandler: function(type, handler){

    this.handlers[type] = [];

},

fire: function(){

    if(!event.target){

        event.target = this;

    }

    if(this.handlers[event.type instanceof Array]){

        var handlers = this.handlers[event.type];

        for(var i = 0, len = handlers.length, i < len; i++){

            handlers[i](event);

        }

    }

},

removeHandler: function(type, handler){

    if(this.handlers[type] instanceof Array){

        var handlers = this.handlers[type];

        for(var i = 0, le = handlers.length; i < len; i++){

            if(handlers[i] === handler){

                break;

            }

        }

        handlers.splice(i, 1);

    }

}

上面是《JavaScript高级程序设计》中的自定义事件实现。于是我们就可以通过addHandler来绑定事件处理函数,用fire来触发事件,用removeHandler来删除事件处理函数。

虽然通过事件解耦了,但流程顺序更加混乱了。

•链式异步

个 人觉得链式操作最值得称赞的还是其解决了异步编程模型的执行流程不清晰的问题。jQuery中$(document).ready就非常好的阐释了这一理 念。DOMCotentLoaded是一个事件,在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。

•Promise

CommonJS中的异步编程模型也延续了这一想法,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。

所以我们可以这样写:

f1().then(f2).then(f3);

这种方法我们无需太过关注实现,也不太需要理解异步,只要懂得通过函数选对象,通过then进行操作,就能进行异步编程。