在 QML 中定义 JavaScript 资源

QML 应用程序的程序逻辑可以使用 JavaScript 定义。JavaScript 代码既可以直接在 QML 文档中定义,也可以分离到 JavaScript 文件中(在 QML 中称为 JavaScript 资源)。

QML 支持两种不同的 JavaScript 资源:代码后实现文件和共享(库)文件。这两种类型的 JavaScript 资源都可以由其他 JavaScript 资源 导入 或包含在 QML 模块 中。

代码后实现资源

大多数导入到 QML 文档中的 JavaScript 文件是为导入它们的 QML 文档定义的状态实现。在这些情况下,文档中定义的每种 QML 对象类型的每个实例都需要一个单独的 JavaScript 对象和状态的副本,以正确行为。

导入 JavaScript 文件时的默认行为是为每个 QML 组件实例提供一个唯一的、隔离的副本。如果该 JavaScript 文件不导入任何带有 .import 声明的资源或模块,其代码将在与 QML 组件实例相同的范围中运行,因此可以访问和操作在该 QML 组件中声明的对象和属性。否则,它将有自己的唯一范围,并且如果需要,应将 QML 组件的对象和属性作为参数传递给 JavaScript 文件的函数。

以下是一个代码后实现资源的示例

// MyButton.qml
import QtQuick 2.0
import "my_button_impl.js" as Logic // A new instance of this JavaScript resource
                                    // is loaded for each instance of Button.qml.

Rectangle {
    id: rect
    width: 200
    height: 100
    color: "red"

    MouseArea {
        id: mousearea
        anchors.fill: parent
        onClicked: Logic.onClicked(rect)
    }
}
// my_button_impl.js
var clickCount = 0;   // this state is separate for each instance of MyButton
function onClicked(button) {
    clickCount += 1;
    if ((clickCount % 5) == 0) {
        button.color = Qt.rgba(1,0,0,1);
    } else {
        button.color = Qt.rgba(0,1,0,1);
    }
}

通常,简单的逻辑应直接在 QML 文件中定义,但更复杂的逻辑应分离到代码后实现资源中,以提高可维护性和可读性。

共享 JavaScript 资源(库)

默认情况下,从 QML 导入的 JavaScript 文件共享它们的上下文与 QML 组件。这意味着 JavaScript 文件可以访问相同的 QML 对象并修改它们。因此,每个导入都必须有这些文件的唯一副本。

前一节介绍了 JavaScript 文件的状态导入。然而,某些 JavaScript 文件是无状态的,更像可重用的库,因为它们提供了一组不需要从它们导入的地方获取任何内容的辅助函数。如果您在以下示例中用特殊的前提标记这样的库,则可以节省大量内存并加快 QML 组件的实例化速度。

// factorial.js
.pragma library

var factorialCount = 0;

function factorial(a) {
    a = parseInt(a);

    // factorial recursion
    if (a > 0)
        return a * factorial(a - 1);

    // shared state
    factorialCount += 1;

    // recursion base-case.
    return 1;
}

function factorialCallCount() {
    return factorialCount;
}

前提声明必须出现在任何(除去注释之外的)JavaScript 代码之前。

请注意,多个 QML 文档可以导入 "factorial.js" 并调用其提供的 factorial 和 factorialCallCount 函数。该 JavaScript 导入的状态在导入它的 QML 文档之间是共享的,因此当某个从未调用 factorial 函数的 QML 文档中调用 factorialCallCount 函数时,其返回值可能非零。

例如

// Calculator.qml
import QtQuick 2.0
import "factorial.js" as FactorialCalculator // This JavaScript resource is only
                                             // ever loaded once by the engine,
                                             // even if multiple instances of
                                             // Calculator.qml are created.

Text {
    width: 500
    height: 100
    property int input: 17
    text: "The factorial of " + input + " is: " + FactorialCalculator.factorial(input)
}

由于是共享的,.pragma 库文件无法直接访问 QML 组件实例对象或属性,尽管可以将 QML 值作为函数参数传递。

© 2024 Qt 公司有限公司。此处包括的文档贡献者是各自所有者的版权。此处提供的文档根据 glyphs.org 发布的 GNU 自由文档许可证 1.3 版本进行许可。Qt 和相关标志是 Qt 公司在芬兰和其他国家的商标。所有其他商标均为其各自所有者的财产。