主页/jQuery教程/回调、延迟与异步/jQuery回调函数管理:$.Callbacks() 详解

jQuery回调函数管理:$.Callbacks() 详解

11,233字
48–71 分钟

概览

目录

$.Callbacks() 是 jQuery 提供的一个多用途回调列表管理对象。它提供了一种强大而灵活的方式来管理函数队列,允许添加、移除、触发和锁定回调函数。这个核心工具常被用于实现观察者模式、事件系统以及作为 $.Deferred 等高级异步机制的基础。深入理解 jQuery回调函数 的管理机制,对于编写模块化、解耦的代码以及掌握 jQuery 内部工作原理具有重要意义。

jQuery.Callbacks() 基础

语法

jQuery.Callbacks( flags )

flags:一个可选的字符串,由空格分隔的标志位组成,用于改变回调列表的行为。

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks 基本示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="fireBtn">触发回调</button>
    <div id="result"></div>

    <script>
        var callbacks = $.Callbacks();

        callbacks.add(function(msg) {
            $('#result').append('<p>回调1: ' + msg + '</p>');
        });

        callbacks.add(function(msg) {
            $('#result').append('<p>回调2: ' + msg + '</p>');
        });

        $('#fireBtn').on('click', function() {
            callbacks.fire('按钮被点击');
        });
    </script>
</body>
</html>

标志位 Flags

标志位字符串用于配置回调列表的行为。可以组合使用,例如 "once memory"

标志位描述
once回调列表仅能被触发一次。再次调用 .fire().fireWith() 将无效。
memory回调列表会记住上一次触发的参数。当新增回调时,会立即使用这些记忆的参数调用该回调。
unique允许在回调列表中每个回调函数只能被添加一次,防止重复添加。
stopOnFalse如果某个回调函数返回 false,则会中断后续回调的执行。

once

语法

var callbacks = $.Callbacks('once');

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks once 示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="fireOnceBtn">触发(仅一次)</button>
    <div id="log"></div>

    <script>
        var callbacks = $.Callbacks('once');
        callbacks.add(function() {
            $('#log').append('<p>回调被执行</p>');
        });

        $('#fireOnceBtn').on('click', function() {
            callbacks.fire(); // 只有第一次点击会有效
            callbacks.fire(); // 后续点击无效果
        });
    </script>
</body>
</html>

memory

语法

var callbacks = $.Callbacks('memory');

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks memory 示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="fireMemoryBtn">触发并记住参数</button>
    <button id="addLaterBtn">添加后加回调</button>
    <div id="output"></div>

    <script>
        var callbacks = $.Callbacks('memory');

        callbacks.add(function(value) {
            $('#output').append('<p>初始回调: ' + value + '</p>');
        });

        $('#fireMemoryBtn').on('click', function() {
            callbacks.fire('第一次触发');
        });

        $('#addLaterBtn').on('click', function() {
            callbacks.add(function(value) {
                $('#output').append('<p>后加回调: ' + value + '</p>');
            });
        });
    </script>
</body>
</html>

unique

语法

var callbacks = $.Callbacks('unique');

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks unique 示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="addBtn">添加回调</button>
    <button id="fireBtn">触发</button>
    <div id="message"></div>

    <script>
        var callbacks = $.Callbacks('unique');
        var fn = function() {
            $('#message').append('<p>回调执行</p>');
        };

        $('#addBtn').on('click', function() {
            callbacks.add(fn); // 多次点击也只会添加一次
            $('#message').append('<p>尝试添加回调</p>');
        });

        $('#fireBtn').on('click', function() {
            callbacks.fire();
        });
    </script>
</body>
</html>

stopOnFalse

语法

var callbacks = $.Callbacks('stopOnFalse');

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks stopOnFalse 示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="fireBtn">触发</button>
    <div id="trace"></div>

    <script>
        var callbacks = $.Callbacks('stopOnFalse');

        callbacks.add(function() {
            $('#trace').append('<p>回调 1 执行</p>');
            return true; // 继续
        });
        callbacks.add(function() {
            $('#trace').append('<p>回调 2 执行,返回 false 停止</p>');
            return false;
        });
        callbacks.add(function() {
            $('#trace').append('<p>回调 3 不会执行</p>');
        });

        $('#fireBtn').on('click', function() {
            callbacks.fire();
        });
    </script>
</body>
</html>

组合使用

多个标志位可以组合使用,例如 "once memory" 创建一个只触发一次但会记住参数的回调列表。

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks 组合标志示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="fireBtn">触发(仅一次)</button>
    <button id="addBtn">添加后加回调</button>
    <div id="result"></div>

    <script>
        var callbacks = $.Callbacks('once memory');

        callbacks.fire('初始化参数'); // 即使触发后添加回调也会立即执行

        $('#fireBtn').on('click', function() {
            callbacks.fire('再次触发'); // 不会生效
        });

        $('#addBtn').on('click', function() {
            callbacks.add(function(msg) {
                $('#result').append('<p>后加回调收到: ' + msg + '</p>');
            });
        });
    </script>
</body>
</html>

方法详解

add()

语法

callbacks.add( callbacks )
callbacks.add( function )
callbacks.add( array )
  • callbacks:另一个 $.Callbacks 对象,将其回调添加到当前列表。
  • function:要添加的回调函数。
  • array:包含多个回调函数的数组。

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks add 方法示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="addBtn">添加多个回调</button>
    <button id="fireBtn">触发</button>
    <div id="display"></div>

    <script>
        var callbacks = $.Callbacks();

        function fn1() { $('#display').append('<p>fn1</p>'); }
        function fn2() { $('#display').append('<p>fn2</p>'); }

        $('#addBtn').on('click', function() {
            callbacks.add([fn1, fn2]); // 使用数组添加
        });

        $('#fireBtn').on('click', function() {
            callbacks.fire();
        });
    </script>
</body>
</html>

remove()

语法

callbacks.remove( function )

function:要从列表中移除的回调函数。

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks remove 方法示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="addBtn">添加回调</button>
    <button id="removeBtn">移除回调</button>
    <button id="fireBtn">触发</button>
    <div id="out"></div>

    <script>
        var callbacks = $.Callbacks();
        var fn = function() { $('#out').append('<p>回调执行</p>'); };

        $('#addBtn').on('click', function() {
            callbacks.add(fn);
        });

        $('#removeBtn').on('click', function() {
            callbacks.remove(fn);
        });

        $('#fireBtn').on('click', function() {
            callbacks.fire();
        });
    </script>
</body>
</html>

fire()

语法

callbacks.fire( arguments )

arguments:传递给回调函数的参数。

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks fire 方法示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="fireArgsBtn">传递参数触发</button>
    <div id="log"></div>

    <script>
        var callbacks = $.Callbacks();
        callbacks.add(function(a, b) {
            $('#log').append('<p>和: ' + (a + b) + '</p>');
        });

        $('#fireArgsBtn').on('click', function() {
            callbacks.fire(5, 3);
        });
    </script>
</body>
</html>

fireWith()

语法

callbacks.fireWith( context [, arguments] )
  • context:回调函数内部的 this 指向。
  • arguments:传递给回调函数的参数数组。

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks fireWith 方法示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="fireWithBtn">触发指定上下文</button>
    <div id="display"></div>

    <script>
        var callbacks = $.Callbacks();
        var obj = { name: '上下文对象' };

        callbacks.add(function() {
            $('#display').append('<p>this.name: ' + this.name + '</p>');
        });

        $('#fireWithBtn').on('click', function() {
            callbacks.fireWith(obj, ['额外参数']); // 参数可传可不传
        });
    </script>
</body>
</html>

disable()

语法

callbacks.disable()

禁用回调列表。此后任何添加、移除、触发等操作都将无效。

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks disable 方法示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="disableBtn">禁用列表</button>
    <button id="fireBtn">触发</button>
    <div id="status"></div>

    <script>
        var callbacks = $.Callbacks();
        callbacks.add(function() {
            $('#status').append('<p>回调触发</p>');
        });

        $('#disableBtn').on('click', function() {
            callbacks.disable();
            $('#status').append('<p>列表已禁用</p>');
        });

        $('#fireBtn').on('click', function() {
            callbacks.fire();
        });
    </script>
</body>
</html>

disabled()

语法

var isDisabled = callbacks.disabled()

返回一个布尔值,表示回调列表是否已被禁用。

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks disabled 方法示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="checkBtn">检查状态</button>
    <button id="disableBtn">禁用列表</button>
    <div id="info"></div>

    <script>
        var callbacks = $.Callbacks();

        $('#checkBtn').on('click', function() {
            $('#info').text('列表是否禁用: ' + callbacks.disabled());
        });

        $('#disableBtn').on('click', function() {
            callbacks.disable();
        });
    </script>
</body>
</html>

lock()

语法

callbacks.lock()

锁定回调列表的当前状态。已触发的列表无法再次触发(除非有 memory 标志)。

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks lock 方法示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="lockBtn">锁定列表</button>
    <button id="fireBtn">触发</button>
    <div id="msg"></div>

    <script>
        var callbacks = $.Callbacks('memory');
        callbacks.add(function() {
            $('#msg').append('<p>回调执行</p>');
        });

        $('#lockBtn').on('click', function() {
            callbacks.lock();
        });

        $('#fireBtn').on('click', function() {
            callbacks.fire();
        });
    </script>
</body>
</html>

locked()

语法

var isLocked = callbacks.locked()

返回一个布尔值,表示回调列表是否已被锁定。

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks locked 方法示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="checkLocked">检查锁定状态</button>
    <button id="lockBtn">锁定</button>
    <div id="result"></div>

    <script>
        var callbacks = $.Callbacks();

        $('#checkLocked').on('click', function() {
            $('#result').text('是否锁定: ' + callbacks.locked());
        });

        $('#lockBtn').on('click', function() {
            callbacks.lock();
        });
    </script>
</body>
</html>

empty()

语法

callbacks.empty()

清空回调列表中的所有函数。

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks empty 方法示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="addBtn">添加回调</button>
    <button id="emptyBtn">清空列表</button>
    <button id="fireBtn">触发</button>
    <div id="log"></div>

    <script>
        var callbacks = $.Callbacks();
        var fn = function() { $('#log').append('<p>回调</p>'); };

        $('#addBtn').on('click', function() {
            callbacks.add(fn);
        });

        $('#emptyBtn').on('click', function() {
            callbacks.empty();
        });

        $('#fireBtn').on('click', function() {
            callbacks.fire();
        });
    </script>
</body>
</html>

has()

语法

callbacks.has( function )

返回一个布尔值,表示指定的回调函数是否存在于列表中。

示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>$.Callbacks has 方法示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="checkBtn">检查是否存在</button>
    <div id="info"></div>

    <script>
        var callbacks = $.Callbacks();
        var fn1 = function() {};
        var fn2 = function() {};

        callbacks.add(fn1);

        $('#checkBtn').on('click', function() {
            var hasFn1 = callbacks.has(fn1);
            var hasFn2 = callbacks.has(fn2);
            $('#info').html('fn1 存在: ' + hasFn1 + '<br>fn2 存在: ' + hasFn2);
        });
    </script>
</body>
</html>

实际应用场景

示例:观察者模式实现

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>观察者模式示例</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
    <button id="updateBtn">发布更新</button>
    <button id="subscribe1">订阅者1</button>
    <button id="subscribe2">订阅者2</button>
    <div id="output"></div>

    <script>
        var publisher = {
            callbacks: $.Callbacks(),
            publish: function(data) {
                this.callbacks.fire(data);
            },
            subscribe: function(fn) {
                this.callbacks.add(fn);
            },
            unsubscribe: function(fn) {
                this.callbacks.remove(fn);
            }
        };

        var subscriber1 = function(data) {
            $('#output').append('<p>订阅者1收到: ' + data + '</p>');
        };
        var subscriber2 = function(data) {
            $('#output').append('<p>订阅者2收到: ' + data + '</p>');
        };

        $('#subscribe1').on('click', function() {
            publisher.subscribe(subscriber1);
        });
        $('#subscribe2').on('click', function() {
            publisher.subscribe(subscriber2);
        });
        $('#updateBtn').on('click', function() {
            publisher.publish('新数据 ' + new Date().toLocaleTimeString());
        });
    </script>
</body>
</html>

版本变更记录

版本变更说明
1.7引入 jQuery.Callbacks() 对象,提供统一的多用途回调列表管理功能。
1.8增强 memory 标志的行为,使其在列表被锁定后仍能正常工作。
1.11修复了与 stopOnFalse 相关的某些边界情况下的行为不一致问题。
3.0优化了内部实现,提高了性能和内存效率。$.Callbacks 的 API 保持不变。
4.0从“slim”构建版本中移除了 $.Callbacks$.Deferred 模块,以减小体积。但完整构建版本中依然保留,功能不变。若需要 IE11 支持,应使用完整构建版本。

浏览器兼容性

基于 jQuery 3.x 或 4.x 版本,$.Callbacks() 的兼容性与 jQuery 核心库一致。对于 jQuery 4.x,已移除对 IE 10 及以下版本的支持。

浏览器类型最低兼容版本(基于 jQuery 3.x/4.x)
PC 端
Chrome60+ (当前及先前主要版本)
Edge15+ (基于 Chromium)
Firefox55+ (当前及先前主要版本)
Opera47+ (当前及先前主要版本)
Safari10+ (当前及先前主要版本)
移动端
Chrome Android100+ (当前版本)
Firefox for Android100+ (当前版本)
Opera Android64+ (当前版本)
Safari on iOS10+
Samsung Internet6.2+
WebView Android100+ (当前版本)
WebView on iOS10+

掌握 $.Callbacks() 这一 jQuery回调函数 管理工具,能够极大地增强代码的灵活性和可维护性。无论是构建自定义事件系统,还是作为更复杂异步流程的基石,$.Callbacks() 都提供了一套简洁而强大的解决方案。通过合理运用不同的标志位和方法,可以精确控制回调函数的执行流程,满足多样化的编程需求。