【问题标题】:QML - what is the id and how does it work?QML - 什么是 id 以及它是如何工作的?
【发布时间】:2017-01-14 08:10:26
【问题描述】:

考虑这个项目结构:

MyComponent.qml:

Item {
    id: innerId
}

Usage.qml:

MyComponent {
    id: outerId
}

乍一看,这似乎创建了一个同时具有 2 个不同 id 的对象。但这是不可能的,如果 id 被视为属性。

在我看来,id 与其说是一个对象的属性,不如说它是一个对象声明的属性。这是真的吗?

它会解释我如何在MyComponent.qml 中将对象称为innerId,在Usage.qml 中将其称为outerId,但在这两个地方它都是同一个对象。

【问题讨论】:

    标签: qt syntax qml semantics identifier


    【解决方案1】:

    id 仅在该 qml 文件中可见。 id 不是属性,而是一个特殊的属性。不要让语法欺骗你,它只是为了符合 qml 的习惯用法,它可能看起来像一个属性,但它完全不同。

    id 属性

    每个 QML 对象类型都只有一个 id 属性。这个属性是 由语言本身提供,不能重新定义或覆盖 通过任何 QML 对象类型。

    可以为对象实例的 id 属性分配一个值,以 允许该对象被其他对象识别和引用。 此 id 必须以小写字母或下划线开头,并且 不能包含除字母、数字和下划线以外的字符。

    从技术上讲,两个 id 似乎都引用了同一个对象,但事实并非如此,innerId 引用了MyComponent.qml 中的Item 实例,outerId 引用了@987654328 中的MyComponetn 实例@。在实践中,如果您从MyComponetnUsage 获得console.log(id),您将获得相同的对象实例,因为MyComponent {} 实例只是来自MyComponent.qmlItem 的另一个名称。

    id 不是属性,只能从该文件内部访问,如果您需要将某些对象公开为从外部可见,则需要这样做:

    Item { // Something.qml
      property Item innerItem : innerId
      Item {
        id: innerId
      }
    }
    

    在我看来,id 与其说是对象的属性,不如说是它 是对象声明的属性。这是真的吗?

    id 用于引用当前 qml 文件中某些 qml 类型的实例。如果“对象声明”是指一个实例,那么是的,这是真的。 IMO“对象”是一个模棱两可的,因为一个对象可以是很多东西,一个对象可以是一个类型、一个实例、一个属性、一个函数、一个JS对象……在这方面我认为“每个QML对象文档中的类型只有一个 id 属性”的措辞不正确。

    id 只适用于 qml 类型的实例,属性和函数以不同的方式工作,并且可以从外部访问。

    如果您需要对其用途进行类比,则 id 可能会被视为类似于私有类成员的东西 - 它仅在类型内部可见,如果您需要将其暴露给外部 - 您需要为它创建一个访问器。

    这似乎创建了一个具有 2 个不同 id 的对象 同时

    这不是真的,因为您将无法使用 innerId 寻址 MyComponent,所以不,它没有 2 个不同的 id,它没有 任何身份证。 id 并不真正属于该对象,它只是在当前源文件中与它相关联。如上所述,两个 id 将引用同一个对象,但该对象没有两个 id。

    它的工作原理(我不是指实际的实现)类似于 C++ 中的引用。您可以在不同的地方使用不同的名称对同一个对象进行多次引用。在 qml 中,您不必像在 C++ 中那样为实例编写名称,但如果您想引用对象,通常的方法是使用 id,尽管根据对象树,您也可以使用 parent 属性。不建议在大型 qml 文件中过度使用 id,因为这可能会降低性能。

    另外,请注意,与 id 不同,您可以非常“覆盖”函数和属性,并且行为有点像 this question 中详细说明的那样,例如,如果您使用字符串属性覆盖 int 属性,则object 最终将拥有该属性两次,但如果您迭代该对象,您将不会找到一个 int 和一个 string,而是两次 string。

    【讨论】:

    • 还有一点,你不能在运行时更改 id,我曾经尝试使用 C++ 更新它但不能。
    • 您不能在运行时更改 id 因为它是一个属性,而不是一个属性。属性是在编译时存在的属性,当 QML 被解析时,而不是在运行时,当 QML 被执行时。
    • @dtech 感谢您的精彩解释。我只是对这两个句子感到困惑:>“从技术上讲,两个 id 似乎都引用了同一个对象,但事实并非如此......”然后 >“...... MyComponent {} 实例只是该项目的另一个名称来自 MyComponent.qml"
    • 我们能否将 ids 视为具有文件范围的全局变量(如 C++ 中匿名命名空间中的变量),它引用该文件中的对象?您还可以详细说明您提到的与 id 过度使用相关的性能下降吗?
    • @pooya13 - id 不是全局的,它们仅在它们被声明的对象树分支中可见。
    猜你喜欢
    • 2020-08-06
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-15
    • 2014-01-09
    • 2017-03-18
    相关资源
    最近更新 更多