首頁  >  文章  >  web前端  >  自己動手實作jQuery Callbacks完整功能程式碼詳解_jquery

自己動手實作jQuery Callbacks完整功能程式碼詳解_jquery

WBOY
WBOY原創
2016-05-16 17:12:35782瀏覽

用法和$.Callbacks完全一致, 但只是實現了add , remove , fire , empty, has和帶參數的構造函數功能,  $.Callbacks 還有disable,disabled, fireWith , fired , lock, locked 方法

 程式碼如下:

 

複製程式碼 程式碼如下:

 String.prototype.trim = function ()
        {
            return this.replace( /^\s+|\s+$/g, '' );
        };

        // Simulate jQuery.Callbacks object
        function MyCallbacks( options )
        {
            var ops = { once: false, memory: false, unique: false, stopOnFalse: false };

            if ( typeof options === 'string' && options.trim() !== '' )
            {
                var opsArray = options.split( /\s+/ );
                for ( var i = 0; i < options.length; i++ )
{
if ( opsArray[i] === 'once' )
ops.once = true;
else if ( opsArray[i] === 'memory' )
ops.memory = true;
else if ( opsArray[i] === 'unique' )
ops.unique = true;
else if ( opsArray[i] === 'stopOnFalse' )
ops.stopOnFalse = true;
}
}

var ar = [];
var lastArgs = null;
var firedTimes = 0;

function hasName( name )
{
var h = false;

if ( typeof name === 'string'
&& name !== null
&& name.trim() !== ''
&& ar.length > 0 )
                {
                    for ( var i = 0; i < ar.length; i++ )
{
if ( ar[i].name === name )
{
h = true;
break;
}
}
}

return h;
}

// add a function
this.add = function ( fn )
{
if ( typeof fn === 'function' )
{
if ( ops.unique )
{
// check whether it had been added before
if ( fn.name !== '' && hasName( fn.name ) )
{
return this;
}
}

ar.push( fn );

if ( ops.memory )
{
// after added , call it immediately
fn.call( this, lastArgs );
}
}

return this;
};

// remove a function
this.remove = function ( fn )
{
if ( typeof ( fn ) === 'function'
&& fn.name !== ''
&& ar.length > 0 )
                {
                    for ( var i = 0; i < ar.length; i++ )
{
if ( ar[i].name === fn.name )
{
ar.splice( i, 1 );
}
}
}

return this;
};

// remove all functions
this.empty = function ()
{
ar.length = 0;
return this;
};

// check whether it includes a specific function
this.has = function ( fn )
{
var f = false;

if ( typeof ( fn ) === 'function'
&& fn.name !== ''
&& ar.length > 0 )
                {
                    for ( var i = 0; i < ar.length; i++ )
{
if ( ar[i].name === fn.name )
{
f = true;
break;
}
}
}

                return f;
            };

            // 逐一調用其中包含的函數
            this.fire = function ( args )
            {
                if ( ops.once &&firedTimes > 0 )
                {
                    返回此信息;
                }

                    var r;

                   , ( var i = 0; i < ar.length; i )

                       r = ar[i].call( this, args );


                       if ( ops.stopOnFalse && r === false )
                      {

                            中斷;

                        }
                    }
                }

                被解僱次數 ;

                  lastArgs = args;

                }

                以這裡回來給
           
 測試函數如下:(注意fn1 fn2是匿名函數,fn2回傳false,fn3是有「名稱」函數)

 




複製程式碼

程式碼如下:

        var fn2 = function ( v )
        {
             return false;
        };

        function fn3( v )

        {

         🎜> 

 1 . 測試add & fire

var cb=new MyCallbacks();

cb.add(fn1)

cb.add(fn2)

cb.add(fn3)

cb.fire('hello')

輸出:

fn1 hello
fn2 hello
fn3 hello

2.測試remove
var cb=new MyCallbacks();

cb.add(fn1)

cb.add(fn2)

cb.add(fn3)

cb.remove(fn1)
cb.fire('hello')
cb.remove(fn3)
cb.fire('hello')
輸出:

fn1 hello
fn2 hello
fn3 hello
----------------------------
fn1 hello
fn2 hello

2.測試has
var cb=new MyCallbacks();

cb.add(fn1)

cb.add(fn2)

cb.add(fn3)

cb.has(fn1) 

cb.has(fn3) 

輸出:

false

---------------

true

3.測試帶參數的建構子 : once

var cb=new MyCallbacks('once')

cb.add(fn1)

cb.fire('hello')

cb.fire('hello')

cb.add(fn2)

cb.fire('hello')

輸出:

hello

-------------------

------------------

------------------------------

4.測試帶參數的建構子 : memory

 var cb=new MyCallbacks('memory')

cb.add(fn1)

cb.fire('hello') // 輸出 : fn1 hello

cb.add(fn2) // 輸出 : fn2 hello

cb.fire('hello')

 輸出 :

 fn1 hello

 fn2 hello

5.測試帶參數的建構子 : stopOnFalse

var cb=new MyCallbacks('stopOnFalse')

cb.add(fn1)

cb.add(fn2)

cb.add(fn3)

cb.fire('hello')

輸出:

fn1 hello
fn2 hello
6.測試帶參數的建構子 :unique

var cb=new MyCallbacks('unique')

 

b.add(fn3)

b.add(fn3)

cb.fire('hello')

輸出:

fn3 hello

 

7. 測試帶組合參數的建構子:四個設定參數可以隨意組合,一下只測試全部組合的情況, 不然要寫16個測試用例 T_T

var cb=new MyCallbacks('once memory unique stopOnFalse')

cb.add(fn1) // 輸出: fn1

cb.add(fn2) // 輸出: fn2

cb.add(fn3) //  輸出: fn3

cb.fire('hello')

輸出:

fn1 hello
fn2 hello
cb.fire('hello') // 輸出:沒有輸出

 

以下是官方API 文件:

Description: A multi-purpose callbacks list object that provides a powerful way to manage callback lists.The $.Callbacks() function is internally used to provide the base functionality behind the jeryDe $. ) components. It can be used as a similar base to define functionality for new components.

建構子 : jQuery.Callbacks( flags )

flags
Type: String
An optional list of space-separated flags that change how the callback list behaves.
Possible flags:
once: Encosurce the call list list like a Deferred).
memory: Keeps track of previous values and will call any callback added after the list has been fired right away with the latest "memorized" values (like a Deferred).< auniques. can only be added once (so there are no duplicates in the list).
stopOnFalse: Interrupts callings when a callback returns false.
By default a callback list will act like an event default a callback list will act like like 2000 月multiple times.

Two specific methods were being used above: .add() and .fire(). The .add() method supports adding new callbacks to the callback list, while the .fire() method executes the added functions and provides way to pass arguments to be processed by the callbacks in the same list.

利用Callbacks 實現發布訂閱模式 pub/sub: (官方文件)

複製程式碼 程式碼如下:

var 主題 = {};

        jQuery.Topic = function ( id )
        {
          方法,
                topic = id && topic[id];

            if ( !topic )

            {
                topic = {
                     訂閱:callbacks.add,
取消訂閱:callbacks.remove
               };
           }   {
                   為主題[id] = topic;
     🎜>            回主體;
        } ;



使用


複製程式碼

程式碼如下:$.Topic( 'mailArrived' ).subscribe( function ( e )        {            console.log( '您有新郵件! ' );<           console.log( "郵件內容: " e.content );        }
        );

        $.Topic( 'mailArrived' ).publish( { title: '郵件標題', content: '郵件內容' } );




實現了其餘的全部功能:callbacks.disable ,callbacks.disabled,  callbacks.fired,callbacks.fireWith,callbacks.lock,callbacks.locked ,然後重構了下程式碼結構,將實現了暫停了匿名函數內,然後透過工廠方法window.callbacks 必須傳回實例,除非每次使用new 。

具體程式碼如下,有興趣和時間的可以對照jQuery版本的回調對比下:



複製程式碼

程式碼如下:


( function ( window, undefined )
{
// Simulate jQuery.Callbacks object
function Callbacks( options )
{
var ops = { once: false, memory: false, unique: false, stopOnFalse: false },
ar = [],
lastArgs = null,
firedTimes = 0,
_disabled = false,
_locked = false;

if ( typeof options === 'string' && options.trim() !== '' )
{
var opsArray = options.split( /\s+/ );
for ( var i = 0; i < options.length; i++ )
{
if ( opsArray[i] === 'once' )
ops.once = true;
else if ( opsArray[i] === 'memory' )
ops.memory = true;
else if ( opsArray[i] === 'unique' )
ops.unique = true;
else if ( opsArray[i] === 'stopOnFalse' )
ops.stopOnFalse = true;
}
}

function hasName( name )
{
var h = false;

if ( typeof name === 'string'
&& name !== null
&& name.trim() !== ''
&& ar.length > 0 )
                    {
                        for ( var i = 0; i < ar.length; i++ )
{
if ( ar[i].name === name )
{
h = true;
break;
}
}
}

return h;
}

// add a function
this.add = function ( fn )
{
if ( typeof fn === 'function' )
{
if ( ops.unique )
{
// check whether it had been added before
if ( fn.name !== '' && hasName( fn.name ) )
{
return this;
}
}

ar.push( fn );

if ( ops.memory )
{
// after added , call it immediately
fn.call( this, lastArgs );
}
}

return this;
};

// remove a function
this.remove = function ( fn )
{
if ( typeof ( fn ) === 'function'
&& fn.name !== ''
&& ar.length > 0 )
                    {
                        for ( var i = 0; i < ar.length; i++ )
{
if ( ar[i].name === fn.name )
{
ar.splice( i, 1 );
}
}
}

return this;
};

// remove all functions
this.empty = function ()
{
ar.length = 0;
return this;
};

// check whether it includes a specific function
this.has = function ( fn )
{
var f = false;

if ( typeof ( fn ) === 'function'
&& fn.name !== ''
&& ar.length > 0 )
                    {
                        for ( var i = 0; i < ar.length; i++ )
{
if ( ar[i].name === fn.name )
{
f = true;
break;
}
}
}

return f;
};

this.disable = function ()
{
_disabled = true;
return this;
};

this.disabled = function ()
{
return _disabled;
};

this.fired = function ()
{
return firedTimes > 0;
                };

                function _fire( context, args )
                {
                    if ( _disabled || ops.once && firedTimes > 0 || _locked )
                    {
                        return;
                    }

                    if ( ar.length > 0 )
                    {
                        var r;

                        for ( var i = 0; i < ar.length; i++ )
                        {
                            r = ar[i].call( context, args );

                            if ( ops.stopOnFalse && r === false )
                            {
                                break;
                            }
                        }
                    }

                    firedTimes++;

                    if ( ops.memory )
                    {
                        lastArgs = args;
                    }

                };

                this.fireWith = function ( context, args )
                {
                    context = context || this;
                    _fire( context, args );
                    return this;
                };

                this.fire = function ( args )
                {
                    _fire( this, args );
                    return this;
                };

                this.lock = function ()
                {
                    _locked = true;
                    return this;
                };

this.locked = function ()
{
return _locked;
};

};

// ファクトリ メソッドとしてグローバルに公開
window.callbacks = function ( options )
{
return new Callbacks( options );
};

} )( window );

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn