Qt Quick 孩子的加载顺序有规定吗?

Ste*_*nov 4 qt qml order-of-execution qtquick2

例如,是否保证子项的初始化顺序与它们在源代码中出现的顺序相匹配?

注意:“初始化子项”是指“初始化子项及其所有子项、后代、绑定等”。

dte*_*ech 6

可以使用一个简单的测试来验证对象创建的顺序。

class Test : public QQuickItem {
    Q_OBJECT
  public:
    Test(QQuickItem * p = 0) : QQuickItem(p) { qDebug() << this; }
};
Run Code Online (Sandbox Code Playgroud)

然后:

  Test {
    objectName: "a"
    Component.onCompleted: console.log(objectName, this)
    Test {
      objectName: "b"
      Component.onCompleted: console.log(objectName, this)
      Test {
        objectName: "c"
        Component.onCompleted: console.log(objectName, this)
      }
      Test {
        objectName: "d"
        Component.onCompleted: console.log(objectName, this)
      }
    }
    Test {
      objectName: "e"
      Component.onCompleted: console.log(objectName, this)
    }
  }
Run Code Online (Sandbox Code Playgroud)

这给出了以下输出:

Test(0x6a7378, parent=0x0, geometry=0,0 0x0)
Test(0x6a73d8, parent=0x0, geometry=0,0 0x0)
Test(0x6a7438, parent=0x0, geometry=0,0 0x0)
Test(0x6a7498, parent=0x0, geometry=0,0 0x0)
Test(0x6a74f8, parent=0x0, geometry=0,0 0x0)
qml: a Test(0x6a7378, "a")
qml: e Test(0x6a74f8, "e")
qml: b Test(0x6a73d8, "b")
qml: d Test(0x6a7498, "d")
qml: c Test(0x6a7438, "c")
Run Code Online (Sandbox Code Playgroud)

这表明对象构造函数确实被称为自下而上。

另请注意, 的顺序onCompleted不同,具体取决于该处理程序的安装位置。如果换TestObj.qml这样的:

Test {
  id: rectangle
  Component.onCompleted: console.log(objectName, this)
}
Run Code Online (Sandbox Code Playgroud)

并像这样声明结构:

  Obj {
    objectName: "a"
    Obj {
      objectName: "b"
      Obj {
        objectName: "c"
      }
      Obj {
        objectName: "d"
      }
    }
    Obj {
      objectName: "e"
    }
  }
Run Code Online (Sandbox Code Playgroud)

然后你会得到一致的“从后到前”输出,这是你在第一个场景中没有得到的:

Test(0x4b2458, parent=0x0, geometry=0,0 0x0)
Test(0x4b24b8, parent=0x0, geometry=0,0 0x0)
Test(0x4b2518, parent=0x0, geometry=0,0 0x0)
Test(0x4b2578, parent=0x0, geometry=0,0 0x0)
Test(0x50f9d68, parent=0x0, geometry=0,0 0x0)
qml: e Test(0x50f9d68, "e")
qml: d Test(0x4b2578, "d")
qml: c Test(0x4b2518, "c")
qml: b Test(0x4b24b8, "b")
qml: a Test(0x4b2458, "a")
Run Code Online (Sandbox Code Playgroud)

然而,所有这些都反映了对象创建的顺序,而不是对象完成的顺序,它涉及到一堆其他的东西,可以以任意顺序执行,具体取决于绑定表达式结构。

简而言之,你不应该真正依赖那个顺序,如果你这样做,你就做错了。你不应该依赖任何比整个 QML 源树完成更好的东西,qtquick 引擎本身会注意延迟绑定表达式的初始化,直到整个对象树完成,所以你不会有问题,它会自动发生,但依赖任何较低级别和细粒度的东西是设计中的潜在缺陷,需要避免。如果您想要更明确的初始化顺序,请提供您的对象 ID,并为整个 qml 文件执行一个单独的初始化表达式,将内容连接在一起。该表达式中的语句将按照它们定义的顺序执行。