Defining JavaScript Resources In QML
QML应用程序的程序逻辑可以使用JavaScript定义. JavaScript代码既可以在QML文档中内联定义, 也可以分离为JavaScript文件(在QML中称为JavaScript Resources
).
QML支持两种不同类型的JavaScript资源: 代码隐藏实现文件和共享(库)文件. 这两种JavaScript资源都可以由其他JavaScript资源imported, 也可以包含在QML modules中.
Code-Behind Implementation Resource
导入QML文档的大多数JavaScript文件是有状态实现. 这种情况下, 文档中定义的QML对象类型的每个实例都需要JavaScript对象和状态的单独副本, 才能正确运行.
导入JavaScript文件时的默认行为是为每个QML组件实例提供一个唯一的, 独立的副本. 如果JavaScript文件不使用.import
语句导入任何资源或模块, 则代码将在与QML组件实例相同的范围内运行, 从而可以访问和操作QML组件中声明的对象和属性. 否则, 它将有自己的唯一作用域, QML组件的对象和属性应作为参数传递给JavaScript文件的函数(如果需要的话).
代码隐藏实现资源的示例如下:
// MyButton.qml import QtQuick 2.0 import "my_button_impl.js" as Logic // a new instance of this JavaScript resource is loaded for each instance of Button.qml Rectangle { id: rect width: 200 height: 100 color: "red" MouseArea { id: mousearea anchors.fill: parent onClicked: Logic.onClicked(rect) } }
// my_button_impl.js var clickCount = 0; // this state is separate for each instance of MyButton 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文件中内联定义, 但更复杂的逻辑应该分离为代码背后的实现资源, 便于维护和可读.
共享的JavaScript资源(库)
默认情况下, 从QML导入的JavaScript文件与QML组件共享上下文. 这意味着JavaScript文件可以访问相同的QML对象, 并可以对其修改.
因此, 每次导入都必须具有这些文件的唯一副本. 上一节介绍了JavaScript文件的有状态导入. 然而, 有些JavaScript文件是无状态的, 更像是可重用的库, 因为它们提供了一组辅助函数, 不需要从导入它们的位置进行任何操作. 如果.pragma标记此类库, 则可以节省大量内存, 并加快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; }
prgma声明必须出现在除注释之外的任何JavaScript代码之前.
注意: 多个QML文档可以导入"factorial.js"
, 并调用它提供的factorial和factorialCallCount函数. JavaScript导入的状态在导入它的QML文档之间共享, 因此当在从不调用factorial函数的QML文件中调用factorialCallCount函数时, 该函数的返回值可能为非零.
例如:
// 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) }
尽管QML值可以作为函数参数传递, 但由于它们是共享的, 因此.pragma库文件不能直接访问QML组件实例对象或属性.