QML 编码规范
本文档包含我们在文档和示例中遵循的 QML 编码约定,并建议大家遵循。
QML 对象声明
在整个文档和示例中,QML 对象属性 总按照以下顺序结构化:
- id
- 属性声明
- 信号声明
- JavaScript 函数
- 对象属性
- 子对象
为了更好的可读性,我们用空行将他们分隔为不同的部分。
例如,有一个 QML 对象 photo,如下所示:
Rectangle { id: photo // id 在第一行,方便找到对象 property bool thumbnail: false // 属性声明 property alias image: photoImage.source signal clicked // 信号声明 function doSomething(x) // JavaScript 函数 { return x + photoImage.width } color: "gray" // 对象属性 x: 20 // 尝试将相关的属性归为一组 y: 20 height: 150 width: { // large bindings 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 } } ] Rectangle { // 子对象 id: border anchors.centerIn: parent; color: "white" Image { id: photoImage anchors.centerIn: parent } } }
分组属性
如果使用了一组属性中的多个属性,建议使用 组表示法,而不是 点表示法,这有助于提高可读性。
例如,下面这个例子:
Rectangle { anchors.left: parent.left; anchors.top: parent.top; anchors.right: parent.right; anchors.leftMargin: 20 } Text { text: "hello" font.bold: true; font.italic: true; font.pixelSize: 20; font.capitalization: Font.AllUppercase }
可以写成这样:
Rectangle { anchors { left: parent.left; top: parent.top; right: parent.right; leftMargin: 20 } } Text { text: "hello" font { bold: true; italic: true; pixelSize: 20; capitalization: Font.AllUppercase } }
不合格的访问
为了提高可读性和性能,始终通过 id 显式引用父组件的属性:
Item { id: root property int rectangleWidth: 50 Rectangle { width: root.rectangleWidth } }
必需的属性
当需要定义在组件之外的数据时,请使用 Required Properties 明确这一点。必须设置 Required properties,否则组件的创建将失败。这些属性比无条件的查找更可取,因为它们的性能更高,并且允许用户和工具对外部属性的类型进行推理。此外,它们还消除了组件对其创建环境的假设。
信号处理
在信号处理程序中处理参数时,使用明确命名它们的函数:
MouseArea { onClicked: (event) => { console.log(`${event.x},${event.y}`); } }
JavaScript 代码
如果脚本是单个表达式,建议将其写为内联的形式:
Rectangle { color: "blue"; width: parent.width / 3 }
如果脚本只有几行,通常使用一个代码块:
Rectangle { color: "blue" width: { var w = parent.width / 3 console.debug(w) return w } }
如果脚本多于几行,或者需要被不同的对象使用,建议创建一个函数并像下面这样调用它:
function calculateWidth(object : Item) : double { var w = object.width / 3 // ... // more javascript code // ... console.debug(w) return w } Rectangle { color: "blue"; width: calculateWidth(parent) }
另请注意,为了更容易地推理和重构你的应用程序,建议给你的函数添加类型注释,因为参数和返回类型都可以从函数签名中立即看到。
对于很长的脚本,建议将函数放在自己的 JavaScript 文件中,并像下面这样导入它:
import "myscript.js" as Script Rectangle { color: "blue"; width: Script.calculateWidth(parent) }
如果代码长度超过一行,并因此在一个代码块内,使用分号来表示每个语句的结尾:
MouseArea { anchors.fill: parent onClicked: { var scenePos = mapToItem(null, mouseX, mouseY); console.log("MouseArea was clicked at scene pos " + scenePos); } }