在 QML 中定义 JavaScript 资源

QML 应用程序的程序逻辑可在 JavaScript 中定义。JavaScript 代码既可以在 QML 文档中以行内定义,也可以分隔成 JavaScript 文件(QML 中称为JavaScript Resources )。

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 文件是无状态的,它们更像是可重用的库,因为它们提供了一组辅助函数,不需要从导入的地方导入任何东西。如果用一个特殊的 pragma 来标记这些库,就能节省大量内存并加快 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;
}

pragma 声明必须出现在任何 JavaScript 代码(不包括注释)之前。

请注意,多个 QML 文档可导入"factorial.js" 并调用它提供的因子和因子调用次数函数。JavaScript 导入的状态会在导入它的 QML 文档中共享,因此在从未调用过阶乘函数的 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 值可作为函数参数传递。

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.