属性绑定#
绑定对象属性
对象属性可以分配一个静态值,该值保持恒定,直到显式分配新值。但是,为了充分利用QML及其内置的动态对象行为支持,大多数QML对象使用属性绑定。
属性绑定是QML的核心特性,允许开发者指定不同对象属性之间的关系。当一个属性的依赖项在值上发生变化时,该属性将自动根据指定的关系进行更新。
在幕后,QML引擎监控属性的相关性(即绑定表达式中的变量)。当检测到变化时,QML引擎会重新评估绑定表达式,并将新结果应用到属性上。
概述#
要创建属性绑定,将属性分配为一个求值的JavaScript表达式,该表达式返回期望的值。在最简单的情况下,绑定可以是另一个属性的引用。以下是一个例子,其中蓝色矩形的长度绑定到其父项的长度
每当父矩形的高度改变时,蓝色矩形的高度会自动更新为相同的数值。
绑定可以包含任何有效的JavaScript表达式或语句,因为QML使用了符合标准的JavaScript引擎。绑定可以访问对象属性、调用方法并使用内置的JavaScript对象,如Date
和Math
。以下是另一个可能用于上述示例的绑定
height: parent.height / 2 height: Math.min(parent.width, parent.height) height: parent.height > 100 ? parent.height : parent.height/2 height: { if (parent.height > 100) return parent.height else return parent.height / 2 } height: someMethodThatReturnsHeight()
以下是涉及更多对象和类型的更复杂示例
在上一个示例中,
topRect.width
依赖于bottomRect.width
和column.width
topRect.height
依赖于column.height
bottomRect.color
依赖于myTextInput.text.length
在语法上,绑定可以具有任意复杂性。但是,如果绑定过于复杂,例如涉及多行或 imperative 循环,则可能表明绑定被用于不仅仅是描述属性关系。复杂的绑定可能会降低代码性能、可读性和可维护性。重新设计具有复杂绑定的组件,或者至少将绑定提取到单独的函数中,可能是一个好主意。作为一个一般规则,用户不应依赖于绑定的评估顺序。
从JavaScript创建属性绑定#
具有绑定的属性将自动根据需要更新。但是,如果以后从JavaScript语句将静态值分配给该属性,则将移除绑定。
例如,下面的矩形最初确保其 高度
总是是其 宽度
的两倍。但是,当按下空格键时,当前 width*3
的值将被赋值给 height
作为 静态 值。之后,高度将保持在这个值不变,即使宽度发生变化。静态值的赋值解除了绑定。
如果意图是给矩形一个固定高度并停止自动更新,那么这不是问题。然而,如果意图是在 width
和 height
之间建立新的关系,那么新的绑定表达式必须用 Qt.binding() 函数包装
现在,按下空格键后,矩形的高度将继续自动更新,始终是宽度的三倍。
调试绑定覆盖#
在 QML 应用程序中,错误地将从 JavaScript 语句中获取的静态值覆盖绑定是一个常见的错误原因。为了帮助开发者追踪此类问题,QML 引擎能够在因命令赋值而丢失绑定时发射消息。
为了生成此类消息,您需要启用 qt.qml.binding.removal
记录类别信息输出,例如通过调用
QLoggingCategory::setFilterRules(QStringLiteral("qt.qml.binding.removal.info=true"));
请参阅 QLoggingCategory 文档以获取有关启用记录类别输出的更多信息。
请注意,在某些情况下,覆盖绑定是非常合理的。QML 引擎生成的任何消息都应被视为诊断辅助工具,而不一定是需要进一步调查的问题的证据。
使用 `` this``
与属性绑定#
当从 JavaScript 创建属性绑定时,可以使用 this
关键字来引用接收绑定的对象。这有助于解决属性名称的不确定性。
例如,下面的 Component.onCompleted
处理程序是在 Item 的作用域内定义的。在这个作用域内,width
指的是 Item 的宽度,而不是矩形的宽度。要将矩形的 height
绑定到其自身的 width
,绑定表达式必须显式引用 this.width
(或者也可以是 rect.width
)