在QML中导入JavaScript资源#

描述如何在QML文档中导入和使用JavaScript资源

JavaScript资源可以由QML文档和其他JavaScript资源导入。JavaScript资源可以通过相对或绝对URL导入。在相对URL的情况下,位置相对于包含导入的QML文档JavaScript资源进行解析。如果脚本文件不可访问,将发生错误。如果JavaScript需要从网络资源获取,组件的status将被设置为“加载中”,直到脚本下载完毕。

JavaScript资源还可以导入QML模块和其他JavaScript资源。在JavaScript资源中的导入语句的语法与在QML文档中的导入语句的语法略有不同,详细说明如下。

从QML文档导入JavaScript资源#

QML文档可以使用以下语法导入JavaScript资源:

import "ResourceURL" as Qualifier

例如

import "jsfile.js" as Logic

导入的JavaScript资源总是使用“as”关键字进行限定。JavaScript资源的限定符必须以大写字母开头,并且必须是唯一的,因此限定符和JavaScript文件之间始终是一对一映射。(这也意味着限定符不能与内置JavaScript对象(如DateMath)的名称相同)。

在导入的JavaScript文件中定义的函数可以通过"Qualifier.functionName(params)"语法获取到导入的QML文档中定义的对象。JavaScript资源中的函数可以接受参数,其类型可以是任何QML值类型或对象类型,以及正常JavaScript类型。在从QML调用此类函数时,将应用正常的数据类型转换规则到参数和返回值。

JavaScript资源中的导入#

QtQuick 2.0中,已添加了对JavaScript资源使用标准的QML导入语法的变体导入其他JavaScript资源以及QML类型命名空间的支持(其中所有之前描述的规则和限定符都适用)。

由于在QtQuick 2.0中JavaScript资源可以通过这种方式导入其他脚本或QML模块,因此定义了一些额外的语义:

  • 具有导入的脚本不会继承由导入它的QML文档导入的导入(例如,访问Component.errorString将失败)

  • 没有导入的脚本将从导入它的QML文档继承导入(例如,访问Component.errorString将成功)

  • 共享脚本(即定义为.pragma library)即使没有导入其他脚本或模块,也不会从任何QML文档继承导入

第一个语义在概念上是正确的,因为特定的脚本可能被任意数量的QML文件导入。第二个语义被保留以支持向后兼容。第三个语义与当前共享脚本语义保持不变,但在这里对此新可能的情况(脚本导入其他脚本或模块)进行了说明。

从其他JavaScript资源导入JavaScript资源

JavaScript资源可以通过以下方式导入另一个资源

import * as MathFunctions from "factorial.mjs";

或者

.import "filename.js" as Qualifier

前者是ECMAScript模块导入的标准ECMAScript语法,只适用于具有.mjs文件扩展名的ECMAScript模块内部。后者是QML引擎提供的JavaScript扩展,也可以与非模块一起使用。作为被ECMAScript标准废除的扩展,其使用是不推荐的。

以这种方式导入JavaScript文件时,它会被附加一个限定符。然后,可以通过限定符(即作为Qualifier.functionName(params))从导入该脚本来访问该文件中的函数。

有时希望在导入上下文中提供的函数不需要进行限定。在这种情况下,应该使用不带as限定符的ECMAScript模块和JavaScript的import语句。

例如,下面的QML代码在script.mjs中调用showCalculations(),而script.mjs反过来又可以调用factorial.mjs中的factorial(),因为它已使用import包含factorial.mjs。

import QtQuick
import "script.mjs" as MyScript

Item {
    width: 100; height: 100

    MouseArea {
        anchors.fill: parent
        onClicked: {
            MyScript.showCalculations(10)
            console.log("Call factorial() from QML:",
                MyScript.factorial(10))
        }
    }
}
// script.mjs
import { factorial } from "factorial.mjs"
export { factorial }

export function showCalculations(value) {
    console.log(
        "Call factorial() from script.js:",
        factorial(value));
}
// factorial.mjs
export function factorial(a) {
    a = parseInt(a);
    if (a <= 0)
        return 1;
    else
        return a * factorial(a - 1);
}

include()函数在另一个JavaScript文件中包含了一个JavaScript文件,而没有使用ECMAScript模块和限定符导入。它将所有来自其他文件的功能和变量都在当前文件的命名空间中可用,但忽略了该文件中的所有pragma和导入。这不是一个好主意,因为函数调用不应该修改调用者的上下文。

include()已被弃用,应避免使用。在Qt的将来版本中将会移除。

从JavaScript资源导入QML模块

JavaScript资源可以通过以下方式导入QML模块

.import TypeNamespace MajorVersion.MinorVersion as Qualifier

下面你可以看到如何使用从javascript导入的模块中的QML类型的一个示例

.import Qt.test 1.0 as JsQtTest

var importedEnumValue = JsQtTest.MyQmlObject.EnumValue3

特别是,这可以在访问由单例类型提供的功能时很有用;有关更多信息,请参阅QML_SINGLETON

默认情况下,你的JavaScript资源可以访问导入该资源的组件的所有导入。如果它被声明为无状态库(使用.pragma library)或包含显式的.import语句,则它无法访问组件的导入。

注意

.import语法在WorkerScript中不适用