Item 0:编码规范
本节提供有关如何格式化属性,信号和函数的顺序,以使事情变得轻松并快速切换到相关代码块。
QML对象属性始终按以下顺序构造:
- id
- 属性声明
- 信号声明
- 对象声明
- 状态(States)
- 变换(Transitions)
- 信号处理器(Signal handlers)
- 子对象
- 可视对象
- Qt提供的不可见对象
- 自定义的不可见对象
- QtObject所包装的私有数据
- JavaScript函数
Rectangle {
id: photo
property bool thumbnail: false // 属性声明
property alias image: photoImage.source
signal clicked // 信号声明
x: 20
y: 20
height: 150
color: "gray" //对象声明
width: { // 较大的绑定
if (photoImage.width > 200) {
photoImage.width;
}
else {
200;
}
}
states: State { // 状态
name: "selected"
PropertyChanges { target: border; color: "red" }
}
transitions: Transition { // 变换
from: ""; to: "selected"
ColorAnimation { target: border; duration: 200 }
}
onSomeEvent: {
}
Rectangle { // 子对象 - 可视对象
id: border
anchors.centerIn: parent; color: "white"
Image { id: photoImage; anchors.centerIn: parent }
}
Timer { } // 子对象 - Qt提供的不可见对象
MyCppObject { } // 子对象 - 自定义的不可见对象
QtObject {
id: privates
property var privateProperty: null
}
function doSomething(x) { // JavaScript 函数
return x + photoImage.width
}
}
信号处理顺序
当处理在Item
上的信号时,要始终记得将Component.onCompleted
放在最后一行.
// 错误的示例
Item {
Component.onCompleted: {
}
onSomeEvent: {
}
}
// Correct
Item {
onSomeEvent: {
}
Component.onCompleted: {
}
}
放在末尾是为了更好的符合心里预期:在组件构造结束时会触发Component.onCompleted。
如果一个Item中有多个信号处理程序,则将行数最少的那些处理程序放在顶部。 随着实现线的增加,处理程序也向下移动。 唯一的例外是Component.onCompleted信号,它始终放在底部。
// 错误示例
Item {
onOtherEvent: {
// Line 1
// Line 2
// Line 3
// Line 4
}
onSomeEvent: {
// Line 1
// Line 2
}
}
// 正确示例
Item {
onSomeEvent: {
// Line 1
// Line 2
}
onOtherEvent: {
// Line 1
// Line 2
// Line 3
// Line 4
}
}
属性的顺序
第一个赋值的属性必须是id。 如果要声明组件的自定义属性,则声明始终位于第一个属性赋值的上方。
// 错误示例
Item {
someProperty: false
property int otherProperty: -1
id: myItem
}
// 正确示例
Item {
id: myItem
property int otherProperty: -1
someProperty: false
}
属性赋值还有一些预定义的顺序。 顺序如下:
- id
- x
- y
- width
- height
- anchors
这里的目标是将最明显和定义最明确的属性放在顶部,以方便访问和查看。 例如,对于图像,我们可能决定将sourceSize也放置在anchors上方。
如果同时还有属性赋值和信号处理器,请确保始终将属性赋值放在信号处理程序上方。
// 错误示例
Item {
onOtherEvent: {
}
someProperty: true
onSomeEvent: {
}
x: 23
y: 32
}
// 正确示例
Item {
x: 23
y: 32
someProperty: true
onOtherEvent: {
}
onSomeEvent: {
}
}
如果将属性赋值与信号处理器混合在一起,通常很难看到它们。 这就是为什么我们将分配放在信号处理程序之上。
函数顺序
尽管QML中没有私有和公共函数,但是我们可以通过使用QtObject进行包装还达成类似的效果
公共函数实现始终放在文件的最底部。
// 错误示例
Item {
function someFunction() {
}
someProperty: true
}
// Correct
Item {
someProperty: true
onOtherEvent: {
}
onSomeEvent: {
}
function someFunction() {
}
}
动画
当使用Animation的任何子类时,尤其是嵌套的子类(如SequentialAnimation)时,请尝试减少一行中的属性数量。 一段时间后,很难推理出同一行中的2-3个以上的赋值。
由于在我们的脑海中很难想象动画,因此我们将受益于使动画尽可能简单,因为它们每帧执行一次。 尝试给他们提供有意义的ID或对象名称,以帮助我们将来在出现问题时对动画进行自我调试。
// 坏的例子
NumberAnimation { target: root; property: "opacity"; duration: root.animationDuration; from: 0; to: 1 }
// Depends on your convention. The line does not exceed 80 characters.
PropertyAction { target: root; property: "visible"; value: true }
// 好的例子
SequentialAnimation {
PropertyAction {
target: root
property: "visible"
value: true
}
NumberAnimation {
target: root
property: "opacity"
duration: root.animationDuration
from: 0
to: 1
}
}
可以放弃部分组件的id
如果一个组件不需要被如何访问,请避免设置id属性。 这样,我们就不会混淆命名空间中的id,或者更可能的产生明明冲突.
最好使用id最多3-4个字符的缩写,以便在查找某个组件(例如TextBox)时,只需键入tb即可列出所有文本框的ID。
命名规则为[组件名缩写] [组件具体描述],例如tbEmail,btnLogIn
TextBox {
id: tbEmail
}
Button {
id: btnSubmit
}
CheckBox {
id: cbAgreement
}
确保最外层的组件使用root作为id
属性赋值
分配分组的属性时,如果只更改一个属性,则始终首选点号。 否则,请始终使用组符号。
Image {
anchors.left: parent.left // 通过. 来访问
sourceSize { // 通过组符号来访问
width: 32
height: 32
}
}
在同一文件中的不同位置将组件分配给Loader的sourceComponent时,请考虑使用相同的实现。 例如,在以下示例中,存在同一组件的两个实例。 如果两个SomeSpecialComponent都是相同的,则最好将SomeSpecialComponent包装在Component中。
// BEGIN 坏的示例.
Loader {
id: loaderOne
sourceComponent: SomeSpecialComponent {
text: "Some Component"
}
}
Loader {
id: loaderTwo
sourceComponent: SomeSpecialComponent {
text: "Some Component"
}
}
// END 坏的示例.
// BEGIN 好的示例.
Loader {
id: loaderOne
sourceComponent: specialComponent
}
Loader {
id: loaderTwo
sourceComponent: specialComponent
}
Component {
id: specialComponent
SomeSpecialComponent {
text: "Some Component"
}
}
// END 好的示例.
这样可以确保无论何时对specialComponent进行更改,它都将在所有装载程序中生效。 在坏的的示例中,我们将必须重复相同的更改。
Import语句
Import在QML中花费时间。而且,如果我们正在开发系统规格较低的设备,那么我们将需要尽可能地优化。在这种情况下,请尝试最小化我们在QML文件中使用的导入次数。
如果还需要导入JavaScript文件,请确保在QML文件和JavaScript文件中都不包含相同的模块。 JavaScript文件共享从QML文件导入的内容,因此我们可以使用用它。
如果不使用QML中导入的modules,请考虑将import语句移至JavaScript文件。但是请注意,一旦在JavaScript文件中导入了某些内容,导入内容将不再共享。有关完整规则,请参见此处。
另外,我们还可以使用Qt.include()复制包含文件的内容,而不必担心导入共享规则。
导入顺序
导入其他模块时,请按照以下顺序进行:
- Qt模块
- 第三方模块
- 本地C ++模块导入
- QML文件夹导入