QML值类型和序列引用

QML值类型QML序列类型必须按值传递。与QML对象类型不同,它们本身没有任何身份,只能作为其他对象的属性或值或作为方法返回的值来访问。每种访问都会隐式地创建一个副本。然而,在JavaScript中,一切都是对象。JavaScript中没有值类型的概念。例如,如果您在JavaScript中执行font.bold = true,我们希望无论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为对象注册其他序列类型。那些将受到影响。

© 2024 The Qt Company Ltd. 本文档中包含的贡献版权归各自所有者所有。本提供的文档在《自由软件基金会 发布的 GNU 自由文档许可证版本 1.3》的条款下许可。Qt 及相关标识是芬兰及/或世界其他国家的 The Qt Company Ltd. 的商标。所有其他商标均为各自所有者的财产。