QML 文档中的 JavaScript 表达式
QML 提供的JavaScript 主机环境可运行有效的标准 JavaScript 结构,如条件运算符、数组、变量设置和循环。除标准 JavaScript 属性外,QML 全局对象(QML Global Object)还包括许多辅助方法,可简化用户界面的构建和与 QML 环境的交互。
QML 提供的 JavaScript 环境比网络浏览器更严格。例如,在 QML 中,您不能添加或修改 JavaScript 全局对象的成员。在普通 JavaScript 中,有可能在未声明的情况下使用变量,从而意外地做到这一点。在 QML 中,这会产生异常,因此所有局部变量都必须明确声明。有关从 QML 执行 JavaScript 代码的限制的完整描述,请参阅 JavaScript环境限制。
QML 文档的不同部分可包含 JavaScript 代码:
- 属性绑定的主体。这些 JavaScript 表达式描述 QML 对象属性之间的关系。当某个属性的依赖关系发生变化时,该属性也会根据指定的关系自动更新。
- 信号处理程序的主体。每当 QML 对象发出相关信号时,这些 JavaScript 语句就会自动评估。
- 自定义方法的定义。在 QML 对象主体中定义的 JavaScript 函数会成为该对象的方法。
- 独立的JavaScript 资源(.js)文件。这些文件实际上独立于 QML 文档,但可导入 QML 文档。导入文件中定义的函数和变量可用于属性绑定、信号处理程序和自定义方法。
属性绑定中的 JavaScript
在下面的例子中,Rectangle 的color
属性依赖于TapHandler 的pressed
属性。这种关系用条件表达式来描述:
import QtQuick 2.12 Rectangle { id: colorbutton width: 200; height: 80; color: inputHandler.pressed ? "steelblue" : "lightsteelblue" TapHandler { id: inputHandler } }
事实上,任何 JavaScript 表达式(无论多么复杂)都可以用于属性绑定定义,只要表达式的结果是一个可以分配给属性的值。这包括副作用。不过,我们不鼓励使用复杂的绑定和副作用,因为它们会降低代码的性能、可读性和可维护性。
定义属性绑定有两种方法:最常见的方法如前文示例中的属性初始化。第二种(也是更罕见的)方式是在 JavaScript 命令代码中为Qt.binding() 函数返回的函数分配属性,如下图所示:
import QtQuick 2.12 Rectangle { id: colorbutton width: 200; height: 80; color: "red" TapHandler { id: inputHandler } Component.onCompleted: { color = Qt.binding(function() { return inputHandler.pressed ? "steelblue" : "lightsteelblue" }); } }
有关如何定义属性绑定的更多信息,请参阅属性绑定文档;有关绑定与值赋值的区别,请参阅属性赋值与属性绑定文档。
信号处理器中的 JavaScript
QML 对象类型可对发生的某些事件发出信号。这些信号可由信号处理函数(signal handler functions)处理,客户端可定义这些函数来实现自定义的程序逻辑。
假设一个 Rectangle 类型的按钮有一个TapHandler 和一个 Text 标签。当用户按下按钮时,TapHandler 会发出tapped 信号。客户端可使用 JavaScript 表达式对onTapped
处理程序中的信号做出反应。QML 引擎会根据需要执行处理程序中定义的 JavaScript 表达式。通常,信号处理程序与 JavaScript 表达式绑定,以启动其他事件或分配属性值。
import QtQuick 2.12 Rectangle { id: button width: 200; height: 80; color: "lightsteelblue" TapHandler { id: inputHandler onTapped: { // arbitrary JavaScript expression console.log("Tapped!") } } Text { id: label anchors.centerIn: parent text: inputHandler.pressed ? "Pressed!" : "Press here!" } }
有关信号和信号处理程序的更多详情,请参阅以下主题:
独立函数中的 JavaScript
程序逻辑也可定义在 JavaScript 函数中。这些函数可以定义在 QML 文档内(作为自定义方法),也可以定义在导入的 JavaScript 文件外部。
自定义方法中的 JavaScript
自定义方法可在 QML 文档中定义,并可从信号处理器、属性绑定或其他 QML 对象中的函数调用。这类方法通常被称为内联 JavaScript 函数,因为它们的实现包含在 QML 对象类型定义(QML 文档)中,而不是外部 JavaScript 文件中。
内联自定义方法的例子如下:
import QtQuick 2.12 Item { function fibonacci(n){ var arr = [0, 1]; for (var i = 2; i < n + 1; i++) arr.push(arr[i - 2] + arr[i -1]); return arr; } TapHandler { onTapped: console.log(fibonacci(10)) } }
每当TapHandler 发出tapped
信号时,fibonacci 函数就会运行。
注意: QML 文档中内联定义的自定义方法会暴露给其他对象,因此 QML 组件中根对象的内联函数可被组件外的调用者调用。如果不希望这样,方法可添加到非根对象中,或最好写在外部 JavaScript 文件中。
有关在 QML 中使用 JavaScript 定义自定义方法的更多信息,请参阅 QMLObject Attributes文档。
在 JavaScript 文件中定义的函数
非繁琐的程序逻辑最好分隔到单独的 JavaScript 文件中。该文件可使用import
语句导入 QML,就像 QML模块一样。
例如,前面例子中的fibonacci()
方法可移入名为fib.js
的外部文件,并像这样访问:
import QtQuick 2.12 import "fib.js" as MathFunctions Item { TapHandler { onTapped: console.log(MathFunctions.fibonacci(10)) } }
有关将外部 JavaScript 文件加载到 QML 的更多信息,请阅读有关在 QML 中导入 JavaScript 资源的章节。
将信号连接到 JavaScript 函数
如上一节所述,发射信号的 QML 对象类型也为它们的信号提供默认信号处理器。但有时,客户端希望在另一个 QML 对象发出信号时,触发 QML 对象中定义的函数。这种情况可通过信号连接来处理。
QML 对象发出的信号可通过调用信号的connect()
方法并把 JavaScript 函数作为参数传递给 JavaScript 函数来连接。例如,下面的代码将TapHandler 的tapped
信号连接到script.js
中的jsFunction()
:
import QtQuick import "script.js" as MyScript Item { id: item width: 200; height: 200 TapHandler { id: inputHandler } Component.onCompleted: { inputHandler.tapped.connect(MyScript.jsFunction) } } | // script.js function jsFunction() { console.log("Called JavaScript function!") } |
每当TapHandler 的tapped
信号发出时,就会调用jsFunction()
。
更多信息,请参阅将信号连接到方法和信号。
应用程序启动代码中的 JavaScript
有时需要在应用程序(或组件实例)启动时运行一些命令代码。虽然把启动脚本作为全局代码包含在外部脚本文件中很有诱惑力,但这会有很大的局限性,因为 QML 环境可能还没有完全建立。例如,有些对象可能尚未创建,有些属性绑定可能尚未建立。有关全局脚本代码的确切限制,请参阅JavaScript 环境限制。
QML 对象完成实例化后,会发出Component.completed
attached 信号。相应Component.onCompleted
处理程序中的 JavaScript 代码会在对象实例化后运行。因此,编写应用程序启动代码的最佳位置是在顶层对象的Component.onCompleted
处理程序中,因为该对象会在 QML 环境完全建立后发出Component.completed
。
例如
import QtQuick 2.0 Rectangle { function startupFunction() { // ... startup code } Component.onCompleted: startupFunction(); }
QML 文件中的任何对象,包括嵌套对象和嵌套 QML 组件实例,都可以使用这个附加属性。如果启动时有多个onCompleted()
处理程序要执行,它们会以未定义的顺序依次运行。
同样,每个Component
在销毁前都会发出destruction() 信号。
© 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.