一、概述
QML提供的JavaScript 的运行宿主环境可以运行有效的标准JavaScript 功能,如条件运算符、数组、变量设置和循环。除了标准的JavaScript属性之外,QML Global对象还包含一些辅助方法,用于简化构建ui以及与QML环境交互的过程。
QML提供的JavaScript环境比web浏览器中严格。例如,在QML中不能添加或修改JavaScript全局对象的成员。在常规的JavaScript中,有可能不小心使用了变量而没有声明它。在QML中,这将抛出异常,因此所有的局部变量都必须显式声明。有关从QML执行JavaScript代码的限制的完整描述,请参阅JavaScript环境限制。
QML文档的不同部分可以包含JavaScript代码,下面就是这些代码可能存在的情况:
- 属性绑定的Js: 这些JavaScript表达式描述了QML对象属性之间的关系。当属性的依赖关系发生变化时,属性也会根据指定的关系自动更新。
- 信号处理 signal handler程序的Js: 每当QML对象发出相关信号时,这些JavaScript语句就会被自动求值。
- 定义自定义方法的JS: 在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在 signal handler 中的应用
QML对象类型可以在某些事件发生时发出信号。这些信号可以通过信号处理函数来处理,这些函数可以由客户端定义来实现自定义的程序逻辑。
假设用Rectangle类型表示的按钮有一个TapHandler和一个Text标签。当用户按下按钮时,TapHandler会发出tap信号。客户端可以使用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文件中外部定义。
1. QML里面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发出tap信号时,fibonacci函数就会运行。
注意: 在QML文档中内联定义的自定义方法将暴露给其他对象,因此QML组件中根对象上的内联函数可以由组件外部的调用者调用。如果不希望这样做,可以将该方法添加到非根对象中,或者最好写在外部JavaScript文件中。
其实就是这个内联方法是有作用区域的。
2. 定义在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资源的部分。
3. 将信号连接到JavaScript函数
发出信号的QML对象类型还为其信号提供默认信号处理程序,如前一节所述。然而,有时客户端希望在另一个QML对象发出信号时触发QML对象中定义的函数。这种情况可以通过信号连接来处理。
通过调用信号的connect()方法并将JavaScript函数作为参数传递,QML对象发出的信号可以连接到JavaScript函数。例如,下面的代码将TapHandler的tap信号连接到script.js中的jsFunction():
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!")
}
只要发出TapHandler的tap信号,jsFunction()就会被调用。
五、在应用程序启动代码中使用JavaScript
有时需要在应用程序(或组件实例)启动时运行一些命令式代码。虽然将启动脚本作为全局代码包含在外部脚本文件中很诱人,但这可能有严重的限制,因为QML环境可能尚未完全建立。例如,一些对象可能还没有创建,或者一些属性绑定可能还没有建立。要了解全局脚本代码的确切限制,请参阅JavaScript环境限制。
当QML对象的实例化完成时,它会发出Component.completed附加信号。对应组件中的JavaScript代码。onCompleted处理程序在对象实例化后运行。因此,编写应用程序启动代码的最佳位置是在组件中。在顶级对象的onCompleted处理程序中,因为当QML环境完全建立时,该对象会发出Component.completed。
例如:
import QtQuick 2.0
Rectangle {
function startupFunction() {
// ... startup code
}
Component.onCompleted: startupFunction();
}
QML文件中的任何对象——包括嵌套的对象和嵌套的QML组件实例——都可以使用这个附加属性。如果启动时要执行多个onCompleted()处理程序,它们将以未定义的顺序顺序运行。文章来源:https://www.toymoban.com/news/detail-769258.html
同样,每个组件在被销毁之前都会发出一个destroy()信号。文章来源地址https://www.toymoban.com/news/detail-769258.html
到了这里,关于QML- JavaScript 表达式在 QML 中使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!