QML语言使用类似于JSON的语法,并允许将各种表达式和方法定义为JavaScript函数。它还允许用户导入JavaScript文件并使用这些导入提供的功能。
这使开发人员和设计人员可以利用他们对JavaScript的了解来快速开发用户界面和应用程序逻辑。
JavaScript表达式
QML具有深层的JavaScript集成,并允许在JavaScript中定义信号处理程序和方法。QML的另一个核心功能是能够使用属性绑定指定和加强对象属性之间的关系,该属性绑定也是使用JavaScript定义的。
有关在QML中使用JavaScript表达式的更多信息,请参见标题为QML文档中的JavaScript表达式的文档页面。
属性绑定中的JavaScript
在下面的例子中,color属性矩形依赖于pressed财产TapHandler。使用条件表达式描述此关系:
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对象类型可以响应某些事件的发生而发出信号。这些信号可以由信号处理程序功能处理,这些功能可以由客户端定义以实现自定义程序逻辑。
假设由Rectangle类型表示的按钮具有TapHandler和Text标签。所述TapHandler发射其抽头当用户按下该按钮信号。客户端可以onTapped使用JavaScript表达式对处理程序中的信号做出反应。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!" } }
有关信号和信号处理程序的更多详细信息,请参考以下主题:
信号和处理程序事件系统
QML对象属性
独立功能中的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文件中。
有关使用JavaScript在QML中定义自定义方法的更多信息,请参见QML对象属性文档。
JavaScript文件中定义的函数
最好将平凡的程序逻辑最好分离到一个单独的JavaScript文件中。可以使用import诸如QML modules之类的语句将该文件导入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对象中定义的功能。此类情况可以通过信号连接来处理。
通过调用信号的connect()方法并将JavaScript函数作为参数传递,可以将QML对象发出的信号连接到JavaScript函数。例如,以下代码将TapHandler的tapped信号连接到jsFunction()in script.js:
import QtQuick 2.12 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!") }
在jsFunction()每当被称为TapHandler的tapped信号被发射。
有关更多信息,请参见将信号连接到方法和信号。
应用程序启动代码中的JavaScript
有时有必要在应用程序(或组件实例)启动时运行一些命令性代码。尽管很容易将启动脚本作为全局代码包含在外部脚本文件中,但由于QML环境可能尚未完全建立,因此这可能会有严重的限制。例如,某些对象可能尚未创建,或者某些属性绑定可能尚未建立。有关全局脚本代码的确切限制,请参见JavaScript环境限制。
当QML对象的实例化完成时,它会发出Component.completed 附加的信号。Component.onCompleted实例化对象后,将运行相应处理程序中的JavaScript代码。因此,编写应用程序启动代码的最佳位置是在Component.onCompleted顶级对象的处理程序中,因为Component.completed在完全建立QML环境时,此对象会发出。
例如:
import QtQuick 2.0 Rectangle { function startupFunction() { // ... startup code } Component.onCompleted: startupFunction();
}QML文件中的任何对象(包括嵌套对象和嵌套QML组件实例)都可以使用此附加属性。如果启动时有多个onCompleted()处理程序要执行,则它们将以不确定的顺序依次运行。
同样,每个对象在被销毁之前都会Component发出destroy()信号。
JavaScript资源
JavaScript函数中定义的应用程序逻辑可以分为单独的JavaScript文件,称为JavaScript资源。有几种不同类型的JavaScript资源,它们具有不同的语义。
有关为QML定义JavaScript资源的更多信息,请参见标题为在QML中定义JavaScript资源的文档页面。
JavaScript导入
QML文档可以导入JavaScript资源,而JavaScript资源可以导入其他JavaScript资源以及QML模块。这使应用程序开发人员可以在模块化的独立文件中提供应用程序逻辑。
有关如何导入JavaScript资源以及如何使用它们提供的功能的更多信息,请参见标题为“ 导入JavaScript资源 ”的文档页面。
JavaScript主机环境
QML引擎提供的JavaScript环境与Web浏览器提供的JavaScript环境有所不同。某些限制适用于在环境中运行的代码,并且QML引擎在根上下文中提供了JavaScript开发人员可能不熟悉的各种对象。
这些限制和扩展记录在QML引擎提供的JavaScript主机环境的说明中。