Qt WebChannel JavaScript API

设置 JavaScript API

要与 QWebChannelWebChannel 通信,客户端必须使用并设置由 qwebchannel.js 提供的 JavaScript API。对于运行在 Qt WebEngine 内的客户端,您可以通过 qrc:///qtwebchannel/qwebchannel.js 载入该文件。对于外部客户端,您需要将文件复制到您的 Web 服务器上。然后创建一个 QWebChannel 对象,并将其传递一个传输对象和一个回调函数,当通道初始化完成后并将发布对象可用时,将调用该回调函数。可选的第三个参数包含一个转换包装函数的数组或单个函数。

传输对象实现了一个最小化的消息传递接口。它应该是一个带有 send() 函数的对象,该函数接收一个字符串化的 JSON 消息并将其传输到服务器端的 QWebChannelAbstractTransport 对象。此外,当收到服务器消息时,应调用其 onmessage 属性。或者,您可以使用 WebSocket 来实施接口。

请注意,在传输对象完全运行后才能构建 JavaScript QWebChannel 对象。对于 WebSocket,这意味着您应该在 socket 的 onopen 处理程序中创建 QWebChannel。请参阅 Qt WebChannel 独立示例 以了解如何完成此操作。

注意: 在同一页面中只能为每个传输创建一个 QWebChannel 对象。

转换包装函数要么是带有内置转换器名称的字符串,要么是用户提供的函数,该函数接受要处理的对象作为参数,并返回结果类型或 undefined(如果函数不适用)。如果返回 undefined,则处理下一个转换器。如果没有转换器返回除 undefined 以外的值,则按正常流程进行处理。"Date" 是目前唯一的内置转换器函数。它接受一个 ISP 8601 日期字符串并返回新的 Date 对象,如果语法正确且日期有效。

与 QObjects 交互

当传给 QWebChannel 对象的回调函数被调用时,通道已初始化完成,并且所有已发布的对象都可以通过 channel.objects 属性在 HTML 客户端进行访问。因此,假设计算机对象使用标识符 "foo" 进行发布,则我们可以按照以下示例进行交互。请注意,HTML 客户端和 QML/C++ 服务器之间的所有通信都是异步的。属性将在 HTML 端进行缓存。此外,请注意,只有能够转换为 JSON 的 QML/C++ 数据类型将正确进行 (反) 序列化,并且因此对 HTML 客户端可访问。

new QWebChannel(yourTransport, function(channel) {

    // Connect to a signal:
    channel.objects.foo.mySignal.connect(function() {
        // This callback will be invoked whenever the signal is emitted on the C++/QML side.
        console.log(arguments);
    });

    // To make the object known globally, assign it to the window object, i.e.:
    window.foo = channel.objects.foo;

    // Invoke a method:
    foo.myMethod(arg1, arg2, function(returnValue) {
        // This callback will be invoked when myMethod has a return value. Keep in mind that
        // the communication is asynchronous, hence the need for this callback.
        console.log(returnValue);
    });

    // Read a property value, which is cached on the client side:
    console.log(foo.myProperty);

    // Writing a property will instantly update the client side cache.
    // The remote end will be notified about the change asynchronously
    foo.myProperty = "Hello World!";

    // To get notified about remote property changes,
    // simply connect to the corresponding notify signal:
    foo.myPropertyChanged.connect(function() {
        console.log(foo.myProperty);
    });

    // One can also access enums that are marked with Q_ENUM:
    console.log(foo.MyEnum.MyEnumerator);
});

重载方法和信号

当你发布一个具有重载方法的 QObject 时,QWebChannel 将将方法调用解析为最佳匹配。请注意,由于 JavaScript 的类型系统,只有一个 'number' 类型最适合映射到 C++ 的 'double'。当重载仅在类似数字参数的类型上有所不同时,QWebChannel 总是选择与 JavaScript 'number' 类型最佳匹配的重载。当你连接到重载信号时,默认情况下,QWebChannel 客户端将只连接到该名称的第一个信号重载。此外,可以显式请求方法的和信号的重载,方法是它们的完整 QMetaMethod 签名。假设在 C++ 方面我们有以下 QObject 子类

class Foo : public QObject
{
    Q_OBJECT
slots:
    void foo(int i);
    void foo(double d);
    void foo(const QString &str);
    void foo(const QString &str, int i);

signals:
    void bar(int i);
    void bar(const QString &str);
    void bar(const QString &str, int i);
};

然后你可以在 JavaScript 端像这样与其进行交互

// methods
foo.foo(42); // will call the method named foo which best matches the JavaScript number parameter, i.e. foo(double d)
foo.foo("asdf"); // will call foo(const QString &str)
foo.foo("asdf", 42); // will call foo(const QString &str, int i)
foo["foo(int)"](42); // explicitly call foo(int i), *not* foo(double d)
foo["foo(QString)"]("asdf"); // explicitly call foo(const QString &str)
foo["foo(QString,int)"]("asdf", 42); // explicitly call foo(const QString &str, int i)

// signals
foo.bar.connect(...); // connect to first signal named bar, i.e. bar(int i)
foo["bar(int)"].connect(...); // connect explicitly to bar(int i)
foo["bar(QString)"].connect(...); // connect explicitly to bar(const QString &str)
foo["bar(QString,int)"].connect(...); // connect explicitly to bar(const QString &str, int i)

© 2024 The Qt Company Ltd. 其中包含的文档贡献是各自所有者的版权。此处提供的文档是在自由软件基金会发布的 GNU 自由文档许可证版本 1.3 条件下许可的。Qt 及其相关标志是 The Qt Company Ltd. 在芬兰以及全球的商标。所有其他商标均为其各自所有者的财产。