一,概述 QML与JS的结合
可以在JavaScript中定义QML应用的程序逻辑。JS既可以在QML文档中定义比如
Text{
text:{
function fn(a,b){
return a+b
}
fn(1,2)
}
}
也可以导入单独的js文件。(作为QML的JavaScript资源)
在QML中,支持两种不同的js资源:基于执行的JS文件、共享的JS文件。
这两种文件都可以导入到其他的js资源中,导入到QML中。
二,基于执行的JS文件
大多数导入到QML文件的JS文件,都是为了对QML文档中的元素进行操作,在这些情况下,每个QML组件实例都需要一个对应的JS对象的复件,这样每个对象实例才会显示正确。
默认情况下,当QML组件类型导入JS文件的时候,一旦QML组件类型实例化,那么每一个实例都会导入唯一的单独的JS文件复件。如果在这个JS文件中,没有import其他的js文件或者模块,那么它的代码运行作用域是和QML组件实例是相同的,可以直接接入和操作QML中声明的属性和对象。否则,它将有自己唯一的作用域,需要的时候,将QML组件作为js文件函数的参数进行操作。
基于执行的js文件 ,示例如下:
MyButton.qml类型
import QtQuick2.0
import "my_button_imp.js" as Logic//将为每一个MyButton实例,复制一个js
Rectangle{
id:rect
width:200;height:100
color:"red"
MouseArea{
id:mousearea
anchors.fill:parent
onClicked:{
Logic.onClicked(rect)
}
}
}
my_button_imp.js
var clickCount=0 //这种状态将分配到每一个实例中,也就是说分开的,
//所以没一个实例的变量都为0
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文件中,复杂的逻辑单独写在js文件中。
总结:每次实例化单个的QML组件,组件中使用的js文件也会为这个实例单独复制出一份。
三,共享js文件(库)
默认情况下,导入到QML文件中js文件,会共享他们的上下文(作用域),这就意味着js可以接入QML文件中的对象(Button,Text等),并且可以修改他们,因此,每一个QML都会对应唯一的js实例,尽管js的内容是相同的。然而,一些js文件不需要保持状态(比如clickCount=0这种变量,不需要每个调用JS文件的QML组件关心这个是不是为0),并且行为可以重用。这类js文件,对使用它的环境没有要求,也无需导入任何数据。通过使用语句”.pragma library“来标识这一类的js文件,不仅可以加速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;
}
多个QML文件可以导入factorial.js文件,并且都可以使用其中的factorial()和factorialCallCount()函数。这种方式的在多个QML文件中,js文件是共享的,只有一个,所以当某个QML文件第一次调用这个js文件的时候,factorialCallCount返回的不一定是0,因为factorialCount可能已经被其他的QML组件修改了,但是没关系,主要使用的是factorial这个函数,而factorialCount只是用来记录次数而已。
示例如下
Calculator.qml
// 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)
}
一旦共享,js文件将不能访问和修改QML文件中的对象,尽管可以传递QML文件对象的值。