QML 值类型和序列引用
QML 值类型和QML 序列类型必须通过值传递。与QML 对象类型相反,它们本身没有特性,只能作为其它对象或值的属性,或作为方法返回的值被访问。每次这样的访问都会隐式地创建一个副本。然而,在 JavaScript 中,一切都是对象。JavaScript 中没有值类型这一概念。例如,如果在 JavaScript 中执行font.bold = true
,无论font
是什么,我们都希望font
的bold
属性被设置。但请看下面的代码片段:
import QtQuick Text { onSomethingHappened: font.bold = true }
在这种情况下,我们知道font
是一个值类型。访问它时,通过调用Q_PROPERTY 的 getter,创建了一个本地副本。然后,我们可以设置它的bold
属性,但这通常只会影响副本,而不会影响原始的Q_PROPERTY 。
为了克服这个问题,QML 提供了引用的概念。当你从一个属性检索一个值或序列类型的实例时,QML 引擎会记住这个属性和值本身。如果值被修改,它就会被写回属性。这样就产生了一个具有独立身份的对象的假象,使上述情况和许多其他情况都能正常工作。
不过,这样做的代价可能会很高。如果序列作为Q_PROPERTY 暴露,那么通过索引访问序列中的任何值都会导致从属性中读取整个序列数据。然后再从该序列数据中检索单个元素。同样,修改序列中的任何值都会导致序列数据被读取。然后执行修改,并将修改后的序列写回属性。如果相关类型是隐式共享的,则读取操作的成本相对较低。修改总是会产生至少一次深度拷贝。
如果从Q_INVOKABLE 函数返回序列或值类型的实例,就可以避免这种开销。返回值不会附加到任何属性,也不会被写回。
默认情况下,对象类型的序列以QQmlListProperty 的形式传递。QQmlListProperty 并不是一个实际的容器,而只是一个视图,或对某些序列存储的引用。因此,QQmlListProperty 不受此影响。但是,您可以使用QML_SEQUENTIAL_CONTAINER 为对象注册其他序列类型。这些将受到影响。
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.